智慧并不产生于学历,而是来自对于知识的终生不懈的追求。这篇文章主要讲述Android-DiskLruCache相关的知识,希望能为你提供帮助。
参考:
1、三分钟学会缓存工具DiskLruCache:
基础使用
2. Android DiskLruCache完全解析,
硬盘缓存的最佳方案:多图片下载setTag避免乱序,
退出程序取消所有下载任务,
LruCache和DiskLruCache的结合使用。
3、Android之本地缓存——LruCache(
内存缓存)
与DiskLruCache(
硬盘缓存)
统一框架:二次采样、Lrucache、DiskLruCache的封装。
简介:
DiskLruCache是一个十分好用的android缓存工具,
我们可以从GitHub上下载其源码:
https://github.com/JakeWharton/DiskLruCache
DiskLruCache所有的数据都存储在/storage/emulated/0/Android/data/应用包名/cache/XXX文件夹中(你也可以修改,
但不建议这样做,
原因请继续往下看),
这个是android系统默认的应用缓存位置,
如果应用被删除,
这个文件也会一起被删除,
避免应用删除后有残留数据的问题。同时,
由于数据没有存储在硬盘里,
所以不会影响系统性能,
在sd卡里,
你可以存储任意多数据。
1、初始化:
由于DiskLruCache是被final修饰的,
因此不可以直接通过new获得它的实例,
我们使用它的open方法获得它的一个实例:
public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
//初始化disklrucache
private void initDiskLruCache() {
try {
File cacheDir =
getDiskCacheDir(this, "
bitmap"
);
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
mDiskLruCache =
DiskLruCache.open(cacheDir, getAppVersion(this), 1,
10 * 1024 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
}
open方法需要四个参数, 第一个是缓存文件文件的位置, 通过下面的方法可得到:
private File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
//如果sd卡存在并且没有被移除
if (Environment.MEDIA_MOUNTED.equals(Environment
.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath =
context.getExternalCacheDir().getPath();
} else {
cachePath =
context.getCacheDir().getPath();
}
return new File(cachePath +
File.separator +
uniqueName);
}
第二个参数是应用程序的版本号, 要传入版本号是因为如果应用升级缓存会被清除掉。通过下面的方法可以获得程序的版本号:
private int getAppVersion(Context context) {
try {
PackageInfo info =
context.getPackageManager().getPackageInfo(
context.getPackageName(), 0);
return info.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return 1;
}
第三个参数表示同一个key可以对应多少个缓存文件, 一般情况下我们都是传1, 这样key和缓存文件一一对应, 查找和移除都会比较方便。
第四个参数表示最大可以缓存多少字节的数据。
2、缓存数据 打开了DiskLruCache之后, 我们可以看看怎么向DiskLruCache中缓存数据:
先来看看从网上down一张图片:
private boolean downloadImg(final String urlStr,
final OutputStream outputStream) {
HttpURLConnection conn =
null;
BufferedOutputStream out =
null;
BufferedInputStream in =
null;
try {
URL url =
new URL(urlStr);
conn =
(HttpURLConnection) url.openConnection();
in =
new BufferedInputStream(conn.getInputStream(), 8 * 1024);
out =
new BufferedOutputStream(outputStream, 8 * 1024);
int len =
0;
while ((len =
in.read()) !=
-1) {
out.write(len);
}
return true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (conn !=
null)
conn.disconnect();
try {
if (out !=
null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (in !=
null)
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
这是一个简单的联网down图片代码, 拿到图片后就可以缓存到本地了, 但是对于每一个存储资源都需要有一个key,这个key要是唯一的, 而且这个key最长120个字符, 且只能包括a-z,0-9,下划线以及减号, 一次我们可以采用java中的UUID来得到key,也可以使用MD5加密网址得到一个key,我这里采用md5, 方法如下:
public class MD5Util {public final static String md5(String pwd) {
//用于加密的字符
char md5String[] =
{ '
0'
, '
1'
, '
2'
, '
3'
, '
4'
, '
5'
, '
6'
, '
7'
, '
8'
, '
9'
,
'
A'
, '
B'
, '
C'
, '
D'
, '
E'
, '
F'
};
try {
//使用平台的默认字符集将此 String 编码为 byte序列,
并将结果存储到一个新的 byte数组中
byte[] btInput =
pwd.getBytes();
// 获得指定摘要算法的 MessageDigest对象,
此处为MD5
//MessageDigest类为应用程序提供信息摘要算法的功能,
如 MD5 或 SHA 算法。
//信息摘要是安全的单向哈希函数,
它接收任意大小的数据,
并输出固定长度的哈希值。
MessageDigest mdInst =
MessageDigest.getInstance("
MD5"
);
//System.out.println(mdInst);
//MD5 Message Digest from SUN, <
initialized>
//MessageDigest对象通过使用 update方法处理数据,
使用指定的byte数组更新摘要
mdInst.update(btInput);
//System.out.println(mdInst);
//MD5 Message Digest from SUN, <
in progress>
// 摘要更新之后,
通过调用digest(
)
执行哈希计算,
获得密文
byte[] md =
mdInst.digest();
//System.out.println(md);
// 把密文转换成十六进制的字符串形式
int j =
md.length;
//System.out.println(j);
char str[] =
new char[j * 2];
int k =
0;
for (int i =
0;
i <
j;
i+
+
) {//i =
0
byte byte0 =
md[i];
//95
str[k+
+
] =
md5String[byte0 >
>
>
4 &
0xf];
//5
str[k+
+
] =
md5String[byte0 &
0xf];
//F
}//返回经过加密后的字符串
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
现在万事俱备, 我们来把图片缓存起来, 由于联网是耗时操作, 所以要在新线程中完成, 完整的方法如下:
private void cacheImg() {
new Thread(new Runnable() {@
Override
public void run() {
String key =
MD5Util.md5(IMGIP);
try {
DiskLruCache.Editor editor =
mDiskLruCache.edit(key);
if (editor !=
null) {
OutputStream out =
editor.newOutputStream(0);
if (downloadImg(IMGIP, out)) {
//提交
editor.commit();
} else {
//撤销操作
editor.abort();
}
}
}/**
* 这个方法用于将内存中的操作记录同步到日志文件(
也就是journal文件)
当中。
* 这个方法非常重要,
因为DiskLruCache能够正常工作的前提就是要依赖于journal文件中的内容。
* 并不是每次写入缓存都要调用一次flush()方法的,
频繁地调用并不会带来任何好处,
* 只会额外增加同步journal文件的时间。
* 比较标准的做法就是在Activity的onPause()方法中去调用一次flush()方法就可以了
*/
mDiskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
editor.newOutputStream(0); 方法有一个参数, 查看源码我们知道这个参数必须大于0并且小于valueCount, 前文中valueCount我们已经设置为1了, 所以这里只能取值0。这个时候打开你的缓存文件夹, /storage/emulated/0/Android/data/应用包名/cache/XXX, 里边已经有了我们缓存的数据了:
文章图片
3、读取缓存 好了, 数据存下来了, 接下来就是读取, 每一个缓存文件都对应一个key, 读取就是根据这个key来读取:
private void showImg() {
String key =
MD5Util.md5(IMGIP);
try {
DiskLruCache.Snapshot snapShot =
mDiskLruCache.get(key);
if(snapShot!=
null){
InputStream is =
snapShot.getInputStream(0);
Bitmap bitmap =
BitmapFactory.decodeStream(is);
im.setImageBitmap(bitmap);
}
} catch (IOException e) {
e.printStackTrace();
}
}
读取的时候我们最先拿到的是一个Snapshot 对象, 再根据我们之前传入的参数0拿到缓存文件的流, 最后把流转换为图片。
到这里大家可能就明白了, 之前的editor.newOutputStream(0); 方法为什么会有一个0的参数了, 相当于一个标识, 读取时也传入参数0才能读到我们想要的数据。( 加入我们的key与缓存文件不是一一对应, 也就是我们一开始的open方法中传入的不是valueCount的值不是1, 那么一个key对应多个缓存文件我们要怎么区分? 就是通过这种方式, 有兴趣的同学查看源码就一目了然了) 。
4、清除缓存
private void clearCache() {
String key =
MD5Util.md5(IMGIP);
try {
mDiskLruCache.remove(key);
} catch (IOException e) {
e.printStackTrace();
}
}
根据缓存文件的key, 调用remove方法, 将该缓存文件移除。
5、获取缓存大小 像凤凰新闻客户端中显示缓存大小, 这个数值我们可以通过size()方法直接拿到:
private void getCacheSize() {
tv.setText(mDiskLruCache.size()+
"
"
);
}
6、清除所有数据
private void deleteAll() {
/**
* 这个方法用于将所有的缓存数据全部删除
* 其实只需要调用一下DiskLruCache的delete()方法就可以实现了。
* 会删除包括日志文件在内的所有文件
*/
try {
mDiskLruCache.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
7、关闭DiskLruCache 所有功能都完成之后, 我们要记得在onDestory方法中关闭DiskLruCache。
@
Override
protected void onDestroy() {
super.onDestroy();
/**
* 这个方法用于将DiskLruCache关闭掉,
是和open()方法对应的一个方法。
* 关闭掉了之后就不能再调用DiskLruCache中任何操作缓存数据的方法,
* 通常只应该在Activity的onDestroy()方法中去调用close()方法。
*/
try {
mDiskLruCache.close();
} catch (IOException e) {
e.printStackTrace();
}
}
郭霖大神的demo: 布局:
activity_main.xml
<
LinearLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:tools=
"
http://schemas.android.com/tools"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
>
<
GridView
android:id=
"
@
+
id/photo_wall"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
android:columnWidth=
"
@
dimen/image_thumbnail_size"
android:gravity=
"
center"
android:horizontalSpacing=
"
@
dimen/image_thumbnail_spacing"
android:numColumns=
"
auto_fit"
android:stretchMode=
"
columnWidth"
android:verticalSpacing=
"
@
dimen/image_thumbnail_spacing"
>
<
/GridView>
<
/LinearLayout>
MainActivity.java
package com.example.photoswalldemo;
import android.app.Activity;
import android.os.Bundle;
import android.view.ViewTreeObserver;
import android.widget.GridView;
/**
* 照片墙主活动,
使用GridView展示照片墙。
*
* http://blog.csdn.net/guolin_blog/article/details/34093441
* Android照片墙完整版,
完美结合LruCache和DiskLruCache
*
* http://blog.csdn.net/guolin_blog/article/details/28863651
*Android DiskLruCache完全解析,
硬盘缓存的最佳方案
*
*
* @
author guolin
*/
public class MainActivity extends Activity {/**
* 用于展示照片墙的GridView
*/
private GridView mPhotoWall;
/**
* GridView的适配器
*/
private PhotoWallAdapter mAdapter;
private int mImageThumbSize;
private int mImageThumbSpacing;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageThumbSize =
getResources().getDimensionPixelSize(
R.dimen.image_thumbnail_size);
mImageThumbSpacing =
getResources().getDimensionPixelSize(
R.dimen.image_thumbnail_spacing);
mPhotoWall =
(GridView) findViewById(R.id.photo_wall);
mAdapter =
new PhotoWallAdapter(this, 0, Images.imageThumbUrls, mPhotoWall);
mPhotoWall.setAdapter(mAdapter);
/*通过getViewTreeObserver()的方式监听View的布局事件,
当布局完成以后,
我们重新修改一下GridView中子View的高度,
以保证子View的宽度和高度可以保持一致。*/
mPhotoWall.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {@
Override
public void onGlobalLayout() {
final int numColumns =
(int) Math.floor(mPhotoWall.getWidth() / (mImageThumbSize +
mImageThumbSpacing));
//Math.floor:求一个浮点数的地板,就是求一个最接近它的整数,它的值小于或等于这个浮点数。
if (numColumns >
0) {
int columnWidth =
(mPhotoWall.getWidth() / numColumns) - mImageThumbSpacing;
mAdapter.setItemHeight(columnWidth);
mPhotoWall.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
}@
Override
protected void onPause() {
super.onPause();
mAdapter.fluchCache();
}@
Override
protected void onDestroy() {
super.onDestroy();
// 退出程序时结束所有的下载任务
mAdapter.cancelAllTasks();
}}
item布局:
photo_layout.xml
<
RelativeLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:tools=
"
http://schemas.android.com/tools"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
>
<
ImageView
android:id=
"
@
+
id/photo"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
android:layout_centerInParent=
"
true"
android:scaleType=
"
fitXY"
/>
<
/RelativeLayout>
PhotoWallAdapter.java
package com.example.photoswalldemo;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Set;
import libcore.io.DiskLruCache;
import libcore.io.DiskLruCache.Snapshot;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.LruCache;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.GridView;
import android.widget.ImageView;
/**
* GridView的适配器,
负责异步从网络上下载图片展示在照片墙上。
* <
p>
* 每次加载图片的时候都优先去【内存缓存】当中读取,
当读取不到的时候则回去【硬盘缓存】中读取,
* 而如果硬盘缓存仍然读取不到的话,
就从【网络】上请求原始数据。不管是从硬盘缓存还是从网络获取,
* 读取到了数据之后都应该添加到内存缓存当中,
这样的话我们下次再去读取图片的时候就能迅速从内存当中读取到,
* 而如果该图片从内存中被移除了的话,
那就重复再执行一遍上述流程就可以了。
* <
p>
* 你完全不需要担心缓存的数据过多从而占用SD卡太多空间的问题,
* DiskLruCache会根据我们在调用open()方法时设定的缓存最大值来自动删除多余的缓存。
* 只有你确定某个key对应的缓存内容已经过期,
需要从网络获取最新数据的时候才应该调用remove()方法来移除缓存。
*
* @
author guolin
*/
public class PhotoWallAdapter extends ArrayAdapter<
String>
{/**
* 记录所有正在下载或等待下载的任务。
*/
private Set<
BitmapWorkerTask>
taskCollection;
/**
* 图片缓存技术的核心类,
用于缓存所有下载好的图片,
在程序内存达到设定值时会将最少最近使用的图片移除掉。
*/
private LruCache<
String, Bitmap>
mMemoryCache;
/**
* 图片硬盘缓存核心类。
*/
private DiskLruCache mDiskLruCache;
/**
* GridView的实例
*/
private GridView mPhotoWall;
/**
* 记录每个子项的高度。
*/
private int mItemHeight =
0;
public PhotoWallAdapter(Context context, int textViewResourceId, String[] objects,
GridView photoWall) {
super(context, textViewResourceId, objects);
mPhotoWall =
photoWall;
taskCollection =
new HashSet<
BitmapWorkerTask>
();
/*首先在PhotoWallAdapter的构造函数中,
我们初始化了LruCache类,
并设置了内存缓存容量为程序最大可用内存的1/8,
紧接着调用了DiskLruCache的open()方法来创建实例,
并设置了硬盘缓存容量为10M,
这样我们就把LruCache和DiskLruCache的初始化工作完成了。*/// 获取应用程序最大可用内存
int maxMemory =
(int) Runtime.getRuntime().maxMemory();
int cacheSize =
maxMemory / 8;
// 设置图片缓存大小为程序最大可用内存的1/8mMemoryCache =
new LruCache<
String, Bitmap>
(cacheSize) {
@
Override
protected int sizeOf(String key, Bitmap bitmap) {
return bitmap.getByteCount();
}
};
try {
// 获取图片缓存路径
File cacheDir =
getDiskCacheDir(context, "
thumb"
);
if (!cacheDir.exists()) {
cacheDir.mkdirs();
}
// 创建DiskLruCache实例,
初始化缓存数据
mDiskLruCache =
DiskLruCache.open(cacheDir, getAppVersion(context), 1, 10 * 1024 * 1024);
//public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
//open()方法接收四个参数,
第一个参数指定的是数据的缓存地址,
第二个参数指定当前应用程序的版本号,
// 第三个参数指定同一个key可以对应多少个缓存文件,
基本都是传1,
第四个参数指定最多可以缓存多少字节的数据。
} catch (IOException e) {
e.printStackTrace();
}
}@
Override
public View getView(int position, View convertView, ViewGroup parent) {
final String url =
getItem(position);
View view;
if (convertView =
=
null) {
view =
LayoutInflater.from(getContext()).inflate(R.layout.photo_layout, null);
} else {
view =
convertView;
}
final ImageView imageView =
(ImageView) view.findViewById(R.id.photo);
if (imageView.getLayoutParams().height !=
mItemHeight) {
imageView.getLayoutParams().height =
mItemHeight;
}
// 给ImageView设置一个Tag,
保证异步加载图片时不会乱序
imageView.setTag(url);
imageView.setImageResource(R.drawable.empty_photo);
loadBitmaps(imageView, url);
return view;
}/**
* 将一张图片存储到LruCache中。
*
* @
param keyLruCache的键,
这里传入图片的URL地址。
* @
param bitmap LruCache的键,
这里传入从网络上下载的Bitmap对象。
*/
public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemoryCache(key) =
=
null) {
mMemoryCache.put(key, bitmap);
}
}/**
* 从LruCache中获取一张图片,
如果不存在就返回null。
*
* @
param key LruCache的键,
这里传入图片的URL地址。
* @
return 对应传入键的Bitmap对象,
或者null。
*/
public Bitmap getBitmapFromMemoryCache(String key) {
return mMemoryCache.get(key);
}/**
* 加载Bitmap对象。此方法会在LruCache中检查所有屏幕中可见的ImageView的Bitmap对象,
* 如果发现任何一个ImageView的Bitmap对象不在缓存中,
就会开启异步线程去下载图片。
*/
public void loadBitmaps(ImageView imageView, String imageUrl) {
try {
Bitmap bitmap =
getBitmapFromMemoryCache(imageUrl);
if (bitmap =
=
null) {
BitmapWorkerTask task =
new BitmapWorkerTask();
taskCollection.add(task);
task.execute(imageUrl);
} else {
if (imageView !=
null &
&
bitmap !=
null) {
imageView.setImageBitmap(bitmap);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}/**
* 取消所有正在下载或等待下载的任务。
*/
public void cancelAllTasks() {
if (taskCollection !=
null) {
for (BitmapWorkerTask task : taskCollection) {
task.cancel(false);
}
}
}/**
* 根据传入的uniqueName获取硬盘缓存的路径地址。
* 当SD卡存在或者SD卡不可被移除的时候,
就调用getExternalCacheDir()方法来获取缓存路径,
否则就调用getCacheDir()方法来获取缓存路径。
* 前者获取到的就是 /sdcard/Android/data/<
application package>
/cache 这个路径,
* 而后者获取到的是 /data/data/<
application package>
/cache 这个路径。
*/
public File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath =
context.getExternalCacheDir().getPath();
} else {
cachePath =
context.getCacheDir().getPath();
}
return new File(cachePath +
File.separator +
uniqueName);
}/**
* 获取当前应用程序的版本号。
*/
public int getAppVersion(Context context) {
try {
PackageInfo info =
context.getPackageManager().getPackageInfo(context.getPackageName(),
0);
return info.versionCode;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return 1;
}/**
* 设置item子项的高度。
*/
public void setItemHeight(int height) {
if (height =
=
mItemHeight) {
return;
}
mItemHeight =
height;
notifyDataSetChanged();
}/**
* 使用MD5算法对传入的key进行加密并返回。MD5第一步
* <
p>
* 直接使用URL来作为key?
不太合适,
因为图片URL中可能包含一些特殊字符,
这些字符有可能在命名文件时是不合法的。
* 其实最简单的做法就是将图片的URL进行MD5编码,
编码后的字符串肯定是唯一的,
并且只会包含0-F这样的字符,
完全符合文件的命名规则。
*/
public String hashKeyForDisk(String key) {
String cacheKey;
try {
final MessageDigest mDigest =
MessageDigest.getInstance("
MD5"
);
mDigest.update(key.getBytes());
cacheKey =
bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey =
String.valueOf(key.hashCode());
}
return cacheKey;
}/**
* 将缓存记录同步到journal文件中。
*/
public void fluchCache() {
if (mDiskLruCache !=
null) {
try {
mDiskLruCache.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}/*
* MD5第二步
* */
private String bytesToHexString(byte[] bytes) {
StringBuilder sb =
new StringBuilder();
for (int i =
0;
i <
bytes.length;
i+
+
) {
String hex =
Integer.toHexString(0xFF &
bytes[i]);
if (hex.length() =
=
1) {
sb.append('
0'
);
}
sb.append(hex);
}
return sb.toString();
}/**
* 异步下载图片的任务。
*
* @
author guolin
*/
class BitmapWorkerTask extends AsyncTask<
String, Void, Bitmap>
{/**
* 图片的URL地址
*/
private String imageUrl;
@
Override
protected Bitmap doInBackground(String... params) {
imageUrl =
params[0];
FileDescriptor fileDescriptor =
null;
FileInputStream fileInputStream =
null;
Snapshot snapShot =
null;
try {
// 生成图片URL对应的key
final String key =
hashKeyForDisk(imageUrl);
//只包含0-F
// 查找key对应的缓存
snapShot =
mDiskLruCache.get(key);
if (snapShot =
=
null) {
// 如果没有找到对应的缓存,
则准备从网络上请求数据,
并写入缓存
DiskLruCache.Editor editor =
mDiskLruCache.edit(key);
if (editor !=
null) {
OutputStream outputStream =
editor.newOutputStream(0);
if (downloadUrlToStream(imageUrl, outputStream)) {
editor.commit();
} else {
editor.abort();
}
}
// 缓存被写入后,
再次查找key对应的缓存
snapShot =
mDiskLruCache.get(key);
}//if (snapShot !=
null) {
//fileInputStream =
(FileInputStream) snapShot.getInputStream(0);
////返回FileDescriptor的标识连接到正在使用此文件输入流文件系统的实际文件的对象。
//fileDescriptor =
fileInputStream.getFD();
//}
// 将缓存数据解析成Bitmap对象
Bitmap bitmap =
null;
//if (fileDescriptor !=
null) {
//bitmap =
BitmapFactory.decodeFileDescriptor(fileDescriptor);
//}
if (snapShot !=
null) {
bitmap =
BitmapFactory.decodeStream(snapShot.getInputStream(0));
}
if (bitmap !=
null) {
// 将Bitmap对象添加到内存缓存LruCache当中
addBitmapToMemoryCache(params[0], bitmap);
}
return bitmap;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileDescriptor =
=
null &
&
fileInputStream !=
null) {
try {
fileInputStream.close();
} catch (IOException e) {
}
}
}
return null;
}@
Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
// 根据Tag找到相应的ImageView控件,
将下载好的图片显示出来。
ImageView imageView =
(ImageView) mPhotoWall.findViewWithTag(imageUrl);
if (imageView !=
null &
&
bitmap !=
null) {
imageView.setImageBitmap(bitmap);
}
taskCollection.remove(this);
}/**
* 建立HTTP请求,
并获取Bitmap对象。
*
* @
param urlString 图片的URL地址
* @
return 解析后的Bitmap对象
*/
private boolean downloadUrlToStream(String urlString, OutputStream outputStream) {
HttpURLConnection urlConnection =
null;
BufferedOutputStream out =
null;
BufferedInputStream in =
null;
try {
final URL url =
new URL(urlString);
urlConnection =
(HttpURLConnection) url.openConnection();
in =
new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);
out =
new BufferedOutputStream(outputStream, 8 * 1024);
int b;
while ((b =
in.read()) !=
-1) {
out.write(b);
}
return true;
} catch (final IOException e) {
e.printStackTrace();
} finally {
if (urlConnection !=
null) {
urlConnection.disconnect();
}
try {
if (out !=
null) {
out.close();
}
if (in !=
null) {
in.close();
}
} catch (final IOException e) {
e.printStackTrace();
}
}
return false;
}}}
【Android-DiskLruCache】图片URL类:
package com.example.photoswalldemo;
public class Images {public final static String[] imageThumbUrls =
new String[] {
"
https://img-my.csdn.net/uploads/201407/26/1406383299_1976.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383291_6518.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383291_8239.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383290_9329.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383290_1042.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383275_3977.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383265_8550.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383264_3954.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383264_4787.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383264_8243.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383248_3693.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383243_5120.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383242_3127.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383242_9576.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383242_1721.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383219_5806.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383214_7794.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383213_4418.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383213_3557.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383210_8779.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383172_4577.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383166_3407.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383166_2224.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383166_7301.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383165_7197.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383150_8410.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383131_3736.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383130_5094.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383130_7393.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383129_8813.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383100_3554.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383093_7894.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383092_2432.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383092_3071.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383091_3119.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383059_6589.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383059_8814.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383059_2237.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383058_4330.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406383038_3602.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382942_3079.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382942_8125.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382942_4881.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382941_4559.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382941_3845.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382924_8955.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382923_2141.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382923_8437.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382922_6166.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382922_4843.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382905_5804.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382904_3362.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382904_2312.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382904_4960.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382900_2418.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382881_4490.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382881_5935.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382880_3865.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382880_4662.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382879_2553.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382862_5375.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382862_1748.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382861_7618.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382861_8606.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382861_8949.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382841_9821.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382840_6603.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382840_2405.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382840_6354.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382839_5779.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382810_7578.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382810_2436.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382809_3883.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382809_6269.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382808_4179.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382790_8326.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382789_7174.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382789_5170.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382789_4118.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382788_9532.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382767_3184.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382767_4772.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382766_4924.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382766_5762.jpg"
,
"
https://img-my.csdn.net/uploads/201407/26/1406382765_7341.jpg"
};
}
推荐阅读
- 手把手教你构建 Android WebView 的缓存机制 & 资源预加载方案
- Ansible Playbook使用指南(如何创建和配置Playbook())
- 如何添加、更新或删除Helm存储库(详细操作指南)
- Ansible如何检查文件是否存在(操作步骤指南)
- 最佳Python IDE和代码编辑器合集(区别和优缺点)
- 什么是Git上游以及如何设置上游分支(详细解析)
- 如何使用Helm回滚更改(使用不同方式实现)
- 如何创建Helm Chart(详细操作分布指南)
- 如何安装和使用Flask(创建简单的应用程序)