图片的三级缓存机制

图片的三级缓存机制

1. 简介

现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多。

现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很 耗流量的应用,其用户数量级肯定要受到影响。当然,我想,向百度美拍这样的应用,必然也有其内部的图片缓存策略。总之,图片缓存是很重要而且是必须的。

 

2.图片缓存的原理

实现图片缓存也不难,需要有相应的cache策略。这里我采用 内存(memory)-本地(local)-网络(Internet) 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且也把它划到缓存的层次结 构中。当根据url向网络拉取图片的时候,先从内存中找,如果内存中没有,再从本地缓存文件中查找,如果缓存文件中也没有,再从网络上通过http请求拉取图 片。在键值对(key-value)中,这个图片缓存的key是图片url的hash值,value就是bitmap。所以,按照这个逻辑,只要一个 url被下载过,其图片就被缓存起来了。

3.图片缓存的比较

## 三级缓存 ##

- 内存缓存, 优先加载, 速度最快
- 本地缓存, 次优先加载, 速度快
- 网络缓存, 不优先加载, 速度慢,浪费流量

网络缓存 NetCacheUtils

  1 /**
  2  * 
  3  * 从网络下载图片
  4  * @author admin
  5  *
  6  */
  7 public class NetCacheUtils {
  8     private LocalCacheUtils mlocalcacheutils;
  9     private MemoryCacheUtils mmemorycacheutils;
 10 
 11     public NetCacheUtils(LocalCacheUtils localcacheutils, MemoryCacheUtils memorycacheutils) {
 12         mlocalcacheutils=localcacheutils;
 13         mmemorycacheutils=memorycacheutils;
 14     }
 15 
 16     public void getBitmapFromNet(ImageView iv_photo, String url) {
 17         // TODO Auto-generated method stub
 18         BitmapTask bitmaptask=new BitmapTask();
 19         bitmaptask.execute(iv_photo,url);//开启AsyncTask,参数在doInBackground获取
 20     }
 21     /*AsyncTask  异步任务即做一些简单的异步处理  ;是handle与线程池的封装
 22      * 第一个泛型:参数类型泛型
 23      * 第二个泛型:更新进度泛型
 24      * 第三个泛型:onProgressUpdate的返回结果的泛型
 25      * 
 26      */
 27     
 28     class BitmapTask extends AsyncTask<Object, Void, Bitmap>{
 29 
 30         private ImageView pic;
 31         private String murl;
 32         /**
 33          * 后台耗时方法在此执行,子线程
 34          */
 35         @Override
 36         protected Bitmap doInBackground(Object... params) {
 37             pic = (ImageView) params[0];
 38             murl = (String) params[1];
 39             
 40             pic.setTag(murl);//将图片与url绑定
 41             return downloadBitmap(murl);
 42         }
 43         /**
 44          * 更新进度,主线程
 45          */
 46         @Override
 47         protected void onProgressUpdate(Void... values) {
 48             // TODO Auto-generated method stub
 49             super.onProgressUpdate(values);
 50         }
 51         /**
 52          * 后台耗时方法结束之后,在此执行,主线程
 53          */
 54         @Override
 55         protected void onPostExecute(Bitmap result) {
 56             if(result!=null){
 57                 
 58                 String tag = (String) pic.getTag();
 59                 if(tag.equals(murl)){
 60                     pic.setImageBitmap(result);
 61                 }
 62                 
 63             }
 64             mlocalcacheutils.setBitmapTolocal(murl, result);
 65             mmemorycacheutils.setBitmapTomemory(murl, result);
 66             System.out.println("从网络上加载图片啦");
 67             
 68         }
 69     }
 70 
 71     /**
 72      * 
 73      * 下载图片
 74      * @return 
 75      */
 76     private Bitmap downloadBitmap(String url){
 77         HttpURLConnection conn=null;
 78         try {
 79             conn=(HttpURLConnection) new URL(url)
 80             .openConnection();
 81             
 82             conn.setConnectTimeout(5000);
 83             conn.setReadTimeout(5000);
 84             conn.setRequestMethod("GET");
 85             conn.connect();
 86             
 87             int responseCode = conn.getResponseCode();//响应码
 88             
 89             if(responseCode==200){//表示成功连接
 90                 InputStream inputStream = conn.getInputStream();
 91                 Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
 92                 return bitmap;
 93             }
 94             
 95         } catch (IOException e) {
 96             
 97             e.printStackTrace();
 98         }
 99         finally{
100             conn.disconnect();
101         }
102         return null;
103         
104     }
105 }

本地缓存 LocalCacheUtils

 

 1 public class LocalCacheUtils {
 2     private static final String CACHE_PATH=Environment.getExternalStorageDirectory()
 3             .getAbsolutePath()+"/zhbj_cache_52";
 4 /**
 5  * 
 6  * 从本地读图片
 7  * @param url
 8  */
 9     public Bitmap getBitmapFromlocal(String url){
10         try {
11             String filename = MD5Encoder.encode(url);
12             
13             File file=new File(CACHE_PATH, filename);//通过父文件夹与自己的文件名称来创建一个文件
14             
15             if(file.exists()){
16                 Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
17                 return bitmap;
18             }
19             
20         } catch (Exception e) {
21             // TODO Auto-generated catch block
22             e.printStackTrace();
23         }
24         return null;
25         
26     }
27     
28 /**
29  * 
30  * 将图片写到本地
31  * @param url
32  * @param bitmap
33  */
34     public void setBitmapTolocal(String url,Bitmap bitmap){
35         try {
36             String filename = MD5Encoder.encode(url);
37             File file=new File(filename);
38             File parentFile = file.getParentFile();
39             if(!parentFile.exists()){//如果文件夾不存在,則创建
40                 file.mkdirs();
41             }
42             //将图片保存到本地
43             bitmap.compress(CompressFormat.JPEG, 100, 
44                     new FileOutputStream(file));
45                 
46     
47         } catch (Exception e) {
48             // TODO Auto-generated catch block
49             e.printStackTrace();
50         }
51         
52     }
53     
54 }

 

内存缓存 MemoryCacheUtils

 1 /**
 2  * 
 3  * 内存缓存
 4  * @author admin
 5  *
 6  */
 7 public class MemoryCacheUtils {
 8  
 9     private HashMap<String, Bitmap> hashlist=new HashMap<String, Bitmap>();
10     /**
11      * 
12      * 从内存中读
13      * @param url
14      * @return
15      */
16     public  Bitmap getBitmapFrommemory(String url){
17         Bitmap bitmap = hashlist.get(url);
18         return bitmap;
19     }
20     
21 
22     /**
23      * 
24      * 写入内存
25      * @param url
26      * @param bitmap
27      */
28     public  void setBitmapTomemory(String url,Bitmap bitmap){
29         hashlist.put(url, bitmap);
30     }
31 }

MyBitmapUtils 调用

 1 /**
 2  * 
 3  * 
 4  * 自定义图片加载工具
 5  * @author admin
 6  *
 7  */
 8 public class MyBitMaputils {
 9     NetCacheUtils netcache;
10     LocalCacheUtils localcacheutils;
11     MemoryCacheUtils memorycacheutils;
12     public MyBitMaputils(){
13         memorycacheutils=new MemoryCacheUtils();
14         localcacheutils=new LocalCacheUtils();
15         netcache=new NetCacheUtils(localcacheutils,memorycacheutils);
16         
17     }
18     Bitmap bitmap =null;
19     public void display(ImageView iv_photo, String url) {
20         iv_photo.setImageResource(R.drawable.news_pic_default);//默认图片,防止图片的复用
21         //内存缓存
22         bitmap= memorycacheutils.getBitmapFrommemory(url);
23         if(bitmap!=null){
24             iv_photo.setImageBitmap(bitmap);
25             System.out.println("从内存中读取图片");
26             return;
27         }
28         //本地缓存
29         bitmap = localcacheutils.getBitmapFromlocal(url);
30         if(bitmap!=null){
31             iv_photo.setImageBitmap(bitmap);
32             memorycacheutils.setBitmapTomemory(url, bitmap);
33             System.out.println("从本地读取图片");
34             return;//从本地读取就不需要从网络读取了
35         }
36         
37         //网络缓存(第一次)
38         netcache.getBitmapFromNet(iv_photo,url);
39     }
40 
41     
42 }

 

posted on 2016-03-12 21:00  oooo呼呼  阅读(2934)  评论(0编辑  收藏  举报