圖片的三級緩存機制


圖片的三級緩存機制

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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM