使用LruCache和DiskLruCache来下载图片

LruCache是一个很好用的图片缓存工具:

主要做法是:滑动图片时将图片的bitmap缓存在LruCache<String, Bitmap>中,退出程序后将图片缓存进文件里,采用DiskLruCache mDiskLruCache

 

所以我们必须设置一个图片缓存的地址:

 

[java] view plain copy
 
  1. public void setImageCache(){  
  2.         String strPath = null;  
  3.         if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {  
  4.             File sdFile = Environment.getExternalStorageDirectory();  
  5.             strPath = sdFile.getAbsolutePath() + "/pic/";  
  6.             File cacheFile = new File(strPath);  
  7.             if(!cacheFile.exists()){  
  8.                 cacheFile.mkdir();  
  9.             }  
  10.         }  
  11.         else{  
  12.             String strCacheDir = this.getCacheDir().getAbsolutePath();  
  13.             strPath = strCacheDir + "/pic/";  
  14.         }  
  15.         setCachePath(strPath);  
  16.     }  
  17.       
  18.     private void setCachePath(String strPicCachePath){  
  19.         if(TextUtils.isEmpty(strPicCachePath)){  
  20.             return;  
  21.         }  
  22.         m_strPicCachePath = strPicCachePath;  
  23.         File cacheFile = new File(strPicCachePath);  
  24.         if(!cacheFile.exists()){  
  25.             cacheFile.mkdir();  
  26.         }  
  27.     }  
  28.       
  29.     public String getCacheBmpPath(String strUrl){  
  30.         if(TextUtils.isEmpty(m_strPicCachePath) || TextUtils.isEmpty(strUrl)){  
  31.             return "";  
  32.         }  
  33.         return m_strPicCachePath + StringUtil.MD5Encode(strUrl) + mFileExName;//".bmp";  
  34.     }  


然后写List的adapter:

 

 

[java] view plain copy
 
  1. private class ListAdapter extends BaseAdapter implements OnScrollListener {  
  2.   
  3.     protected List<ShopData> items = new ArrayList<ShopData>();  
  4.     protected static final int FETCH_IMAGE_MSG = 1;  
  5.     private LruCache<String, Bitmap> mMemoryCache;  
  6.     protected HashSet<ImageView> mItemsMissingImages = new HashSet<ImageView>();  
  7.     protected ImageLoaderHandler mHandler;  
  8.     protected ImageLoader mImageFetcher;  
  9.     public static final int TIMEOUT = 30000;//超时时间30秒  
  10.     private DiskLruCache mDiskLruCache;    
  11.   
  12.     public ListAdapter() {  
  13.         super();  
  14.         mHandler = new ImageLoaderHandler();  
  15.         int maxMemory = (int) Runtime.getRuntime().maxMemory();  
  16.         int mCacheSize = maxMemory / 8;  
  17.         // 给LruCache分配1/8 4M  
  18.         mMemoryCache = new LruCache<String, Bitmap>(mCacheSize) {  
  19.   
  20.             // 必须重写此方法,来测量Bitmap的大小  
  21.             @Override  
  22.             protected int sizeOf(String key, Bitmap value) {  
  23.                 return value.getRowBytes() * value.getHeight();  
  24.             }  
  25.   
  26.         };  
  27.           
  28.      try {  
  29.         mDiskLruCache = DiskLruCache    
  30.                         .open(new File(m_strPicCachePath), getAppVersion(MainActivityTest.this), 1, 10 * 1024 * 1024);  
  31.     } catch (IOException e) {  
  32.         e.printStackTrace();  
  33.     }    
  34.   
  35.     }  
  36.       
  37.     /** 
  38.      * 将缓存记录同步到journal文件中。 
  39.      */  
  40.     public void fluchCache() {  
  41.         if (mDiskLruCache != null) {  
  42.             try {  
  43.                 mDiskLruCache.flush();  
  44.             } catch (IOException e) {  
  45.                 e.printStackTrace();  
  46.             }  
  47.         }  
  48.     }  
  49.       
  50.   
  51.     @Override  
  52.     public int getCount() {  
  53.         return items.size();  
  54.     }  
  55.   
  56.     @Override  
  57.     public Object getItem(int position) {  
  58.         return items.get(position);  
  59.     }  
  60.   
  61.     @Override  
  62.     public long getItemId(int position) {  
  63.         return position;  
  64.     }  
  65.   
  66.     @Override  
  67.     public View getView(int position, View convertView, ViewGroup parent) {  
  68.   
  69.         ShopDataTag tag = new ShopDataTag();  
  70.         if (convertView == null) {  
  71.             convertView = mInflater.inflate(R.layout.listitem, null);  
  72.             tag.name = (TextView) convertView.findViewById(R.id.name);  
  73.             tag.shopInfo = (TextView) convertView.findViewById(R.id.info);  
  74.             tag.icon = (ImageView) convertView.findViewById(R.id.image_icon);  
  75.             convertView.setTag(tag);  
  76.         } else {  
  77.             tag = (ShopDataTag) convertView.getTag();  
  78.         }  
  79.   
  80.         TextView name = tag.name;  
  81.         TextView info = tag.shopInfo;  
  82.         ImageView imageView = tag.icon;  
  83.         ShopData data = items.get(position);  
  84.         name.setText(data.name);  
  85.         info.setText(data.info);  
  86.         imageView.setTag(data.url);  
  87.         setContactPhoto(data.url, imageView);  
  88.         return convertView;  
  89.     }  
  90.       
  91.       
  92.     protected void setContactPhoto(String url,ImageView viewToUse) {  
  93.         if(TextUtils.isEmpty(url)) {  
  94.             viewToUse.setImageResource(R.drawable.avatar);  
  95.         }else{  
  96.             //先看mMemoryCache里能不能得到bitmap  
  97.             Bitmap bitmap = mMemoryCache.get(url);    
  98.             if (bitmap != null) {  
  99.                 viewToUse.setImageBitmap(bitmap);  
  100.             } else {  
  101.                 Snapshot snapShot = null;  
  102.                 FileDescriptor fileDescriptor = null;  
  103.                 FileInputStream fileInputStream = null;  
  104.                 try {  
  105.                     //因为mDiskLruCache会把key作为文件名,所以把url通过md5转换为key  
  106.                     final String key = hashKeyForDisk(url);  
  107.                     snapShot = mDiskLruCache.get(key);  
  108.                     //如果snapShot为空,就是没找到对应的文件  
  109.                     if (snapShot == null) {  
  110.                         //这里去下载  
  111.                         fetchImage(viewToUse);  
  112.                     }else{  
  113.                         fileInputStream = (FileInputStream) snapShot.getInputStream(0);  
  114.                         fileDescriptor = fileInputStream.getFD();  
  115.                         if (fileDescriptor != null) {  
  116.                             bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);  
  117.                         }  
  118.                         //如果解析文件成bitmap失败,重新下载  
  119.                         if(!TextUtils.isEmpty(url) && bitmap != null){  
  120.                             mMemoryCache.put(url, bitmap);  
  121.                             viewToUse.setImageBitmap(bitmap);  
  122.                         }else{  
  123.                             fetchImage(viewToUse);  
  124.                         }  
  125.                     }  
  126.                 }catch(IOException ex) {  
  127.                     ex.printStackTrace();  
  128.                 }finally{  
  129.                     if (fileDescriptor == null && fileInputStream != null) {  
  130.                         try {  
  131.                             fileInputStream.close();  
  132.                         } catch (IOException e) {  
  133.                         }  
  134.                     }  
  135.                 }  
  136.                   
  137.                   
  138.             }  
  139.         }  
  140.     }  
  141.       
  142.       
  143.     private void fetchImage(ImageView viewToUse) {  
  144.         viewToUse.setImageResource(R.drawable.avatar);  
  145.         mItemsMissingImages.add(viewToUse);  
  146.         if (mScrollState != OnScrollListener.SCROLL_STATE_FLING) {  
  147.             sendFetchImageMessage(viewToUse);  
  148.         }  
  149.     }  
  150.       
  151.     public String <strong>hashKeyForDisk</strong>(String key) {     将key转换为md5文件  
  152.         return StringUtil.MD5Encode(key);  
  153.     }  
  154.       
  155.   
  156.     // image downloader  
  157.     private class ImageLoaderHandler extends Handler {  
  158.         @Override  
  159.         public void handleMessage(Message message) {  
  160.             if (isFinishing()) {  
  161.                 return;  
  162.             }  
  163.             switch (message.what) {  
  164.             case FETCH_IMAGE_MSG: {  
  165.                 final ImageView imageView = (ImageView) message.obj;  
  166.                 if (imageView == null) {  
  167.                     break;  
  168.                 }  
  169.   
  170.                 final String url = (String) imageView.getTag();  
  171.                 if (TextUtils.isEmpty(url)) {  
  172.                     break;  
  173.                 }  
  174.                   
  175.                 Bitmap map = getBitmapFromMemCache(url);  
  176.                 if (map == null) {  
  177.                     break;  
  178.                 }  
  179.                   
  180.                 synchronized (imageView) {  
  181.                     final String myUrl = (String) imageView.getTag();  
  182.                     if (TextUtils.equals(url, myUrl)) {  
  183.                         imageView.setImageBitmap(map);  
  184.                         mItemsMissingImages.remove(imageView);  
  185.                     } else {  
  186.                     }  
  187.                 }  
  188.                 break;  
  189.             }  
  190.             }  
  191.         }  
  192.   
  193.         public void clearImageFecthing() {  
  194.             removeMessages(FETCH_IMAGE_MSG);  
  195.         }  
  196.     }  
  197.   
  198.     private class ImageLoader implements Runnable {  
  199.         String url;  
  200.         private ImageView mImageView;  
  201.   
  202.         public ImageLoader(String url, ImageView imageView) {  
  203.             this.url = url;  
  204.             this.mImageView = imageView;  
  205.         }  
  206.   
  207.         public void run() {  
  208.             if (isFinishing()) {  
  209.                 return;  
  210.             }  
  211.   
  212.             if (Thread.interrupted()) {  
  213.                 return;  
  214.             }  
  215.   
  216.             FileDescriptor fileDescriptor = null;  
  217.             FileInputStream fileInputStream = null;  
  218.             Snapshot snapShot = null;  
  219.             try {  
  220.                 final String key = hashKeyForDisk(url);  
  221.                 snapShot = mDiskLruCache.get(key);  
  222.                 if (snapShot == null) {  
  223.                     // 如果没有找到对应的缓存,则准备从网络上请求数据,并写入缓存  
  224.                     DiskLruCache.Editor editor = mDiskLruCache.edit(key);  
  225.                     if (editor != null) {  
  226.                         OutputStream outputStream = editor.newOutputStream(0);  
  227.                         boolean flag = downloadImage(url, outputStream);  
  228.                         if (flag) {  
  229.                             editor.commit();  
  230.                         } else {  
  231.                             editor.abort();  
  232.                         }  
  233.                     }  
  234.                     // 缓存被写入后,再次查找key对应的缓存  
  235.                     snapShot = mDiskLruCache.get(key);  
  236.                 }  
  237.                 //这里应该删除对应的文件  
  238.                   
  239.                 if (snapShot != null) {  
  240.                     fileInputStream = (FileInputStream) snapShot.getInputStream(0);  
  241.                     fileDescriptor = fileInputStream.getFD();  
  242.                 }  
  243.                   
  244.                 // 将缓存数据解析成Bitmap对象  
  245.                 Bitmap bitmap = null;  
  246.                 if (fileDescriptor != null) {  
  247.                     bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);  
  248.                 }  
  249.                 if (bitmap != null) {  
  250.                     // 将Bitmap对象添加到内存缓存当中  
  251.                     mMemoryCache.put(url, bitmap);  
  252.                 }  
  253.             } catch (IOException e) {  
  254.                 e.printStackTrace();  
  255.             } finally {  
  256.                 if (fileDescriptor == null && fileInputStream != null) {  
  257.                     try {  
  258.                         fileInputStream.close();  
  259.                     } catch (IOException e) {  
  260.                     }  
  261.                 }  
  262.             }  
  263.               
  264.   
  265.             if (Thread.interrupted()) {  
  266.                 return;  
  267.             }  
  268.   
  269.             Message msg = new Message();  
  270.             msg.what = FETCH_IMAGE_MSG;  
  271.             msg.obj = mImageView;  
  272.             mHandler.sendMessage(msg);  
  273.         }  
  274.     }  
  275.       
  276.     public Bitmap getBitmapFromMemCache(String key) {    
  277.         return mMemoryCache.get(key);    
  278.     }   
  279.       
  280.       
  281.       
  282.     public boolean downloadImage(String strUrl,OutputStream fos) {  
  283.           
  284.         URL getUrl = null;  
  285.         Bitmap bitmap = null;  
  286.         BufferedOutputStream out = null;  
  287.         BufferedInputStream in = null;  
  288.         try {  
  289.             getUrl = new URL(strUrl);  
  290.         } catch (MalformedURLException ex) {  
  291.             Log.e("HttpUtil", "get MalformedURL", ex);  
  292.             return false;  
  293.         }  
  294.         InputStream input = null;  
  295.         HttpURLConnection conn = null;  
  296.         try {  
  297.             conn =  (HttpURLConnection)getUrl.openConnection();  
  298.             conn.setConnectTimeout(TIMEOUT);  
  299.             conn.setReadTimeout(TIMEOUT);  
  300.             conn.setDoInput(true);  
  301.             conn.connect();  
  302.             input = conn.getInputStream();  
  303.             in = new BufferedInputStream(input, 8 * 1024);  
  304.             out = new BufferedOutputStream(fos, 8 * 1024);  
  305.             int b;  
  306.             while ((b = in.read()) != -1) {  
  307.                 out.write(b);  
  308.             }  
  309.             return true;  
  310.         } catch (Exception ex) {  
  311.             Log.e("HttpUtil", "downloadImage", ex);  
  312.         } catch(OutOfMemoryError ex){  
  313.             ex.printStackTrace();  
  314.         } finally {  
  315.             try {  
  316.                 if(out != null){  
  317.                     out.close();  
  318.                     out = null;  
  319.                 }  
  320.                 if (in != null){  
  321.                     in.close();  
  322.                     in = null;  
  323.                 }  
  324.                 if (conn != null){  
  325.                     conn.disconnect();  
  326.                     conn = null;  
  327.                 }  
  328.             } catch (Exception ex) {  
  329.                 Log.e("HttpUtil", "downloadImage finally", ex);  
  330.             }  
  331.         }  
  332.         return false;  
  333.     }  
  334.       
  335.       
  336.     private boolean getResponse(InputStream input, OutputStream os, byte[] data) throws IOException{  
  337.         if(input == null || os == null || data == null){  
  338.             return false;  
  339.         }  
  340.         int i = 0;  
  341.         while( (i = input.read(data)) != -1){  
  342.             os.write(data, 0, i);  
  343.             os.flush();  
  344.         }  
  345.         os.flush();  
  346.         return true;  
  347.     }  
  348.       
  349.     private void processMissingImageItems(AbsListView view) {  
  350.         for (ImageView iv : mItemsMissingImages) {  
  351.             sendFetchImageMessage(iv);  
  352.         }  
  353.     }  
  354.   
  355.     protected void sendFetchImageMessage(ImageView view) {  
  356.         final String url = (String) view.getTag();  
  357.         if (TextUtils.isEmpty(url)) {  
  358.             return;  
  359.         }  
  360.         mImageFetcher = new ImageLoader(url, view);  
  361.         synchronized (MainActivityTest.this) {  
  362.             if (sImageFetchThreadPool == null) {  
  363.                 sImageFetchThreadPool = Executors.newFixedThreadPool(3);  
  364.             }  
  365.             sImageFetchThreadPool.execute(mImageFetcher);  
  366.         }  
  367.     }  
  368.   
  369.     public void clearImageFetching() {  
  370.         synchronized (MainActivityTest.this) {  
  371.             if (sImageFetchThreadPool != null) {  
  372.                 sImageFetchThreadPool.shutdownNow();  
  373.                 sImageFetchThreadPool = null;  
  374.             }  
  375.         }  
  376.   
  377.         mHandler.clearImageFecthing();  
  378.     }  
  379.   
  380.     public void clearMessages() {  
  381.         if (mHandler != null) {  
  382.             try {  
  383.                 mHandler.removeCallbacksAndMessages(null);  
  384.             } catch (java.lang.Throwable th) {  
  385.             }  
  386.             mHandler = null;  
  387.         }  
  388.     }  
  389.       
  390.     @Override  
  391.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  392.         mScrollState = scrollState;  
  393.         if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {  
  394.             clearImageFetching();  
  395.         } else {  
  396.             processMissingImageItems(view);  
  397.         }  
  398.     }  
  399.   
  400.     @Override  
  401.     public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {  
  402.   
  403.     }  
  404.   
  405. }  
  406.   
  407. private class ShopDataTag {  
  408.     TextView name;  
  409.     TextView shopInfo;  
  410.     ImageView icon;  
  411. }  

 

效果图:

代码:http://download.csdn.net/detail/baidu_nod/7777137

posted @ 2016-11-28 22:10  天涯海角路  阅读(95)  评论(0)    收藏  举报