您的位置:首页 > 移动开发 > Android开发

android图片的三级缓存

2016-03-19 16:55 471 查看
一、图片的三级缓存
1. 内存
1. 内存的引用
1. 强引用
特点:没有变量引用 ,就会被垃圾回收线程收到,直到程序崩溃,也不会回收
2. 软引用
特点:垃圾回收线程执行,不一定会回收,内存不足的时候,崩溃之前,清理软引用
3. 弱引用
特点:垃圾回收线程一跑,就被回收
4. 虚引用
特点:垃圾回收一跑也被清理,该应用获取的数据都为null

2. 针对android系统
1. LruCache
内存不足时,回收该容器中的数据
2. 本地(硬盘)
文件:
sdcard

app(/data/data/包名/cache)

sharedpreferences
3. 网络
网络读取

二、使用操作

1. 先从内存取
2. 再从本地文件中
3. 从网络取

三、加载网络图片错位
1. 标记

四、代码

public class BitmapCacheUtils
{

//动态获取jvm的内存

private int maxSize = (int) (Runtime.getRuntime().freeMemory() / 2);
//图片的缓存容器
private LruCache<String, Bitmap> memCache = new LruCache<String, Bitmap>(maxSize) {

@Override
protected int sizeOf(String key, Bitmap value) {
// TODO Auto-generated method stub
return value.getRowBytes() * value.getHeight();
}

};
//保留最后一次访问url的信息
private Map<ImageView,String> urlImageViewDatas = new HashMap<ImageView, String>();

private File cacheDir ;
private MainActivity mainActivity;
private ExecutorService    threadPool;

public BitmapCacheUtils(MainActivity mainActivity) {
this.mainActivity = mainActivity;
//获取当前app的cache目录
cacheDir = mainActivity.getCacheDir();
//线程池
threadPool = Executors.newFixedThreadPool(6);
}
public void display(ImageView iv, String ivUrl) {
<span style="color:#FF0000;"> // 1. 先从内存取</span>

Bitmap bitmap = memCache.get(ivUrl);
if (bitmap != null) {
System.out.println("从内存获取数据");
//缓存中有图片
iv.setImageBitmap(bitmap);
return;
}

<span style="color:#FF0000;"> // 2. 再从本地文件中, app(/data/data/包名/cache)</span>
bitmap = getCacheFile(ivUrl);
if (bitmap != null) {
System.out.println("从文件获取数据");
//本地文件中有图片
iv.setImageBitmap(bitmap);
return;
}

<span style="color:#FF0000;"> // 3. 从网络取</span>
urlImageViewDatas.put(iv, ivUrl);//保留最后一次访问的url
getBitmapFromNet(iv, ivUrl);
}

private void getBitmapFromNet(ImageView iv, String ivUrl) {
//new Thread(new DownLoadUrl(iv, ivUrl)).start();
//线程池
threadPool.submit(new DownLoadUrl(iv, ivUrl));
}

private class DownLoadUrl implements Runnable{
private String ivUrl;
private ImageView iv;
public DownLoadUrl(ImageView iv,String ivUrl){
this.iv = iv;
this.ivUrl = ivUrl;
}
@Override
public void run() {
//访问网络
try {
URL url = new URL(ivUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(6000);//设置超时时间
con.setRequestMethod("GET");
int code = con.getResponseCode();
if (code == 200) {
//请求成功
InputStream inputStream = con.getInputStream();
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
//1.往内存中添加
memCache.put(ivUrl, bitmap);

//2.往本地文件中添加
saveBitmapToCacheFile(bitmap,ivUrl);

//3.显示数据
mainActivity.runOnUiThread(new Runnable() {

@Override
public void run() {
System.out.println("从网络获取数据");

// 显示图片
// 判断url是不是最新的
//是最新的 自己的数据
if (ivUrl.equals(urlImageViewDatas.get(iv))) {
//自己的数据
iv.setImageBitmap(bitmap);
}
}
});

}

} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

/**
* 保存bitmap到cache目录的文件中
* @param bitmap
* @param ivUrl
*/
public void saveBitmapToCacheFile(Bitmap bitmap,String ivUrl) {
File file = new File(cacheDir,Md5Utils.md5(ivUrl));
try {
bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(file));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* @param ivUrl
*     当做缓存图片的名字
* @return
*/
public Bitmap getCacheFile(String ivUrl){
//把ivUrl转换MD5值,再把md5 做文件名
File file = new File(cacheDir,Md5Utils.md5(ivUrl));
if (file != null  && file.exists()) {
//文件存在
//把文件转换成bitmap
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());

//再往内存写
memCache.put(ivUrl, bitmap);
return bitmap;
} else {
//不存在
return null;
}

}

}

五、MD5工具类<pre name="code" class="java">public class Md5Utils {

/**
* @param path
*    ?????·??
* @return
*    ?????MD5?
*/
public static String getFileMD5(String path){
StringBuilder mess = new StringBuilder();
try {
FileInputStream fis = new FileInputStream(new File(path));
//???MD5??????
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[10240];
int len = fis.read(buffer);
while (len != -1) {
md.update(buffer, 0, len);
//??????
len = fis.read(buffer);
}
byte[] digest = md.digest();
for (byte b : digest){
//???????????16??????
int d = b & 0xff;// 0x000000ff
String hexString = Integer.toHexString(d);
if (hexString.length() == 1) {//?????4λ?0
hexString = "0" + hexString;
}
hexString = hexString.toUpperCase();
mess.append(hexString);//????????????2λ??????????????????

}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mess + "";
}
public static String md5(String str){
StringBuilder mess = new StringBuilder();
try {
//???MD5??????
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] bytes = str.getBytes();
byte[] digest = md.digest(bytes);

for (byte b : digest){
//???????????16??????
int d = b & 0xff;// 0x000000ff
String hexString = Integer.toHexString(d);
if (hexString.length() == 1) {//?????4λ?0
hexString = "0" + hexString;
}
mess.append(hexString);//????????????2λ??????????????????

}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return mess + "";
}
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: