閱讀405 返回首頁    go 技術社區[雲棲]


android異步圖片加載三之handler+線程池+消息隊列模式+緩存

https://blog.csdn.net/soesa/article/details/7787922

假象現在有這樣一個需求:

      一個微博客戶端或者多媒體客戶端需要從服務端拉取一些數據,該數據中包含了很多圖片,如果不用異步加載方式,可能會使主線程阻塞導致ANR異常,但是異步加載後如果每次都通過網絡去下載圖片,性能上會差很多,而且也會浪費流量,導致用戶的不滿,故現在增加一個緩存用來存儲圖片,緩存中包含內存存儲和sdcard存儲。先從緩存中去,在緩存中先從內存中取出,如果內存中沒有再從sdcard去,如果sdcard中存在則直接返回該圖片資源並放入內存中,如果兩者都沒有則從網絡上下載,下載後並放入sdcard中供下次使用,這樣就節約了資源開銷,下麵是主要代碼:

PicManager(用來處理圖片的操作):

[java] view plaincopy
  1. public class PicManager {  
  2.   
  3.     private Map<String,SoftReference<Bitmap>> imgCache ;  
  4.     private Context ctx;  
  5.       
  6.     public PicManager(Map<String,SoftReference<Bitmap>> imgCache,Context ctx) {  
  7.         this.ctx = ctx;  
  8.         this.imgCache = imgCache;  
  9.     }  
  10.       
  11.       
  12.     /** 
  13.      * 從網絡上下載 
  14.      * @param url 
  15.      * @return 
  16.      */  
  17.     public Bitmap getBitMapFromUrl(String url) {  
  18.         Bitmap bitmap = null;  
  19.         URL u =null;  
  20.         HttpURLConnection conn = null;  
  21.         InputStream is = null;  
  22.         try {  
  23.             u = new URL(url);  
  24.             conn = (HttpURLConnection)u.openConnection();  
  25.             is = conn.getInputStream();  
  26.             bitmap = BitmapFactory.decodeStream(is);  
  27.         } catch (Exception e) {  
  28.             e.printStackTrace();  
  29.         }  
  30.         return bitmap;  
  31.     }  
  32.       
  33.     /** 
  34.      * 從文件中讀取 
  35.      * @return 
  36.      * @throws Exception  
  37.      */  
  38.     private Bitmap getBitMapFromSDCard(String url) throws Exception {  
  39.         Bitmap bitmap = null;  
  40.         String filename = MD5Util.getMD5(url);  
  41.         FileInputStream fis = ctx.openFileInput(filename);  
  42.         bitmap = BitmapFactory.decodeStream(fis);  
  43.         return bitmap;  
  44.     }  
  45.       
  46.     /** 
  47.      * 從緩存中讀取 
  48.      * @param url 
  49.      * @return 
  50.      * @throws Exception  
  51.      */  
  52.     public Bitmap getImgFromCache(String url) throws Exception {  
  53.         Bitmap bitmap = null;  
  54.         //從內存中讀取  
  55.         if(imgCache.containsKey(url)) {  
  56.             synchronized (imgCache) {  
  57.                 SoftReference<Bitmap> bitmapReference = imgCache.get(url);  
  58.                 if(null != bitmapReference) {  
  59.                     bitmap = bitmapReference.get();  
  60.                 }  
  61.             }  
  62.         } else {//否則從文件中讀取  
  63.             bitmap = getBitMapFromSDCard(url);  
  64.             //將圖片保存進內存中  
  65.             imgCache.put(url, new SoftReference<Bitmap>(bitmap));  
  66.         }  
  67.         return bitmap;  
  68.     }  
  69.       
  70.     /** 
  71.      * 將圖片寫入sdcard中 
  72.      * @param bitmap 
  73.      * @param url 
  74.      * @throws Exception 
  75.      */  
  76.     public void writePic2SDCard(Bitmap bitmap,String url) throws Exception {  
  77.         String filename = MD5Util.getMD5(url);  
  78.         FileOutputStream fos = ctx.openFileOutput(filename, ctx.MODE_APPEND);  
  79.         byte[] bitmapByte = PictureUtil.bitmap2Byte(bitmap);  
  80.         ByteArrayInputStream bis = new ByteArrayInputStream(bitmapByte);  
  81.         int len = 0;  
  82.         byte[] b = new byte[bis.available()];  
  83.         while((len = bis.read(b)) != -1) {  
  84.             fos.write(b, 0, len);  
  85.         }  
  86.         if(null != bis) {  
  87.             bis.close();  
  88.         }  
  89.         if(null != fos) {  
  90.             fos.close();  
  91.         }  
  92.     }  
  93. }  

 ImgLoader(用來加在圖片):


[java] view plaincopy
  1. public class ImgLoader {  
  2.   
  3.     private Map<String,SoftReference<Bitmap>> imgCache = new HashMap<String,SoftReference<Bitmap>>();  
  4.     private Context ctx;  
  5.       
  6.     public ImgLoader(Context ctx) {  
  7.         this.ctx = ctx;  
  8.     }  
  9.       
  10.     private PicManager manager = new PicManager(imgCache,ctx);  
  11.     private Handler handler = new Handler();  
  12.       
  13.       
  14.     private ExecutorService threadPool = Executors.newFixedThreadPool(5);  
  15.       
  16.     public Bitmap loadImg(final String url,final ImgCallback callback) {  
  17.           
  18.         //先從緩存中讀取圖片資源  
  19.         Bitmap bitmap = null;  
  20.         try {  
  21.             bitmap = manager.getImgFromCache(url);;  
  22.               
  23.             if(null == bitmap) {  
  24.                 //開啟線程從網絡上下載  
  25.                 threadPool.submit(new Runnable() {//submit方法確保下載是從線程池中的線程執行  
  26.                     @Override  
  27.                     public void run() {  
  28.                         final Bitmap bitmapFromUrl = manager.getBitMapFromUrl(url);  
  29.                         try {  
  30.                             manager.writePic2SDCard(bitmapFromUrl,url);  
  31.                         } catch (Exception e) {  
  32.                             e.printStackTrace();  
  33.                         }  
  34.                         handler.post(new Runnable() {  
  35.                             @Override  
  36.                             public void run() {  
  37.                                 callback.refresh(bitmapFromUrl);  
  38.                             }  
  39.                         });  
  40.                     }  
  41.                 });  
  42.             } else {  
  43.                   
  44.             }  
  45.         } catch (Exception e) {  
  46.             e.printStackTrace();  
  47.         }  
  48.         return bitmap;  
  49.     }  
  50.       
  51. }  

 ImgCallback callback是一個接口,用來刷新界麵


[java] view plaincopy
  1. public interface ImgCallback {  
  2.   
  3.       
  4.     public void refresh(Bitmap bitmap);  
  5. }  

最後更新:2017-04-03 19:13:18

  上一篇:go DatagramSocket類簡單實現文件下載
  下一篇:go Print2Flash出現&quot;System Error. Code:1722. RPC服務器不可用.&quot;錯誤解決辦法