继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Android图片三级缓存策略,简单直接。

忽然笑
关注TA
已关注
手记 191
粉丝 64
获赞 275

 1.简介 

    Android对于图片的优化,一直都有的。第三方的框架imageloader到Picasso、glide、Fresco,各领风骚,但谁也不能独步武林,一统江湖。但是他们核心的缓存原理都是一样,我们也可以自己封装。

   三级缓存:

     1.内存缓存:缓存在内存中,基于LRU(least recently used )算法,机器重启消失。

     2.本地缓存。缓存在本地中。一般键值对形式。(url,filepath)

     3.网络缓存。从网络加载资源,然后缓存在内存、本地中。

2.实现步骤

   2.1 内存缓存:

  1. public class MemoryCacheUtils {  

  2.       private LruCache<String,Bitmap> mMemoryCache;  

  3.       public MemoryCacheUtils(){  

  4.           long maxMemory = Runtime.getRuntime().maxMemory()/8;//得到手机最大允许内存的1/8,即超过指定内存,则开始回收  

  5.           //需要传入允许的内存最大值,虚拟机默认内存16M,真机不一定相同  

  6.           mMemoryCache=new LruCache<String,Bitmap>((int) maxMemory){  

  7.               //用于计算每个条目的大小  

  8.               @Override  

  9.               protected int sizeOf(String key, Bitmap value) {  

  10.                   int byteCount = value.getByteCount();  

  11.                   return byteCount;  

  12.               }  

  13.           };  

  14.       }  

  15.       /** 

  16.        * 从内存中读图片 

  17.        * @param url 

  18.        */  

  19.       public Bitmap getBitmapFromMemory(String url) {  

  20.           //Bitmap bitmap = mMemoryCache.get(url);//1.强引用方法  

  21.           /*2.弱引用方法 

  22.           SoftReference<Bitmap> bitmapSoftReference = mMemoryCache.get(url); 

  23.           if (bitmapSoftReference != null) { 

  24.               Bitmap bitmap = bitmapSoftReference.get(); 

  25.               return bitmap; 

  26.           } 

  27.           */  

  28.           if(url==null||"".equals(url)){  

  29.               return null;  

  30.           }  

  31.           Bitmap bitmap = mMemoryCache.get(url);  

  32.             

  33.           return bitmap;  

  34.   

  35.       }  

  36.       /** 

  37.        * 往内存中写图片 

  38.        * @param url 

  39.        * @param bitmap 

  40.        */  

  41.       public void setBitmapToMemory(String url, Bitmap bitmap) {  

  42.           //mMemoryCache.put(url, bitmap);//1.强引用方法  

  43.           /*2.弱引用方法 

  44.           mMemoryCache.put(url, new SoftReference<>(bitmap)); 

  45.           */  

  46.           mMemoryCache.put(url,bitmap);  

  47.       }  

  48. }  

 2.2本地缓存


  1. public class LocalCacheUtils {  

  2.      private static final String CACHE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath()+"/my/images";  

  3.      /** 

  4.       * 从本地读取图片 

  5.       * @param url 

  6.       */  

  7.      public Bitmap getBitmapFromLocal(String url){  

  8.          String fileName = null;//把图片的url当做文件名,并进行MD5加密  

  9.          try {  

  10.              fileName = MD5Encoder.encode(url);    //这里加不加密无所谓  

  11.              File file=new File(CACHE_PATH,fileName);  

  12.              Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));  

  13.              return bitmap;  

  14.          } catch (Exception e) {  

  15.              e.printStackTrace();  

  16.          }  

  17.          return null;  

  18.      }  

  19.   

  20.      /** 

  21.       * 从网络获取图片后,保存至本地缓存 

  22.       * @param url 

  23.       * @param bitmap 

  24.       */  

  25.      public void setBitmapToLocal(String url,Bitmap bitmap){  

  26.          try {  

  27.                

  28.              String fileName = MD5Encoder.encode(url);//把图片的url当做文件名,并进行MD5加密  

  29.              File file=new File(CACHE_PATH,fileName);  

  30.   

  31.              //通过得到文件的父文件,判断父文件是否存在  

  32.              File parentFile = file.getParentFile();  

  33.              if (!parentFile.exists()){  

  34.                  parentFile.mkdirs();  

  35.              }  

  36.              //把图片保存至本地  

  37.              bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));  

  38.          } catch (Exception e) {  

  39.              e.printStackTrace();  

  40.          }  

  41.   

  42.      }  

  43. }  

  2.3网络缓存


  1. public class NetCacheUtils {  

  2.     private LocalCacheUtils mLocalCacheUtils;  

  3.     private MemoryCacheUtils mMemoryCacheUtils;  

  4.   

  5.     public NetCacheUtils(LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {  

  6.         mLocalCacheUtils = localCacheUtils;  

  7.         mMemoryCacheUtils = memoryCacheUtils;  

  8.     }  

  9.     public NetCacheUtils(){  

  10.           

  11.     }  

  12.     /** 

  13.      * 从网络下载图片 

  14.      * @param ivPic 显示图片的imageview 

  15.      * @param url   下载图片的网络地址 

  16.      */  

  17.     public void getBitmapFromNet(ImageView ivPic, String url) {  

  18.         new BitmapTask().execute(ivPic, url);//启动AsyncTask  

  19.   

  20.     }  

  21.       

  22.       

  23.     public void getBitmapFromNet(View ivPic, String url) {  

  24.         new BitmapTask_view().execute(ivPic, url);//启动AsyncTask  

  25.   

  26.     }  

  27.     public Bitmap getBitmapFromNet(final String url) {  

  28.         //启动AsyncTask  

  29.         return null;  

  30.     }  

  31.     /** 

  32.      * AsyncTask就是对handler和线程池的封装 

  33.      * 第一个泛型:参数类型 

  34.      * 第二个泛型:更新进度的泛型 

  35.      * 第三个泛型:onPostExecute的返回结果 

  36.      */  

  37.     class BitmapTask extends AsyncTask<Object, Void, Bitmap> {  

  38.   

  39.         private ImageView ivPic;  

  40.         private String url;  

  41.   

  42.         /** 

  43.          * 后台耗时操作,存在于子线程中 

  44.          * @param params 

  45.          * @return 

  46.          */  

  47.         @Override  

  48.         protected Bitmap doInBackground(Object[] params) {  

  49.             ivPic = (ImageView) params[0];  

  50.             url = (String) params[1];  

  51.   

  52.             return downLoadBitmap(url);  

  53.         }  

  54.   

  55.         /** 

  56.          * 更新进度,在主线程中 

  57.          * @param values 

  58.          */  

  59.         @Override  

  60.         protected void onProgressUpdate(Void[] values) {  

  61.             super.onProgressUpdate(values);  

  62.         }  

  63.   

  64.         /** 

  65.          * 耗时方法结束后执行该方法,主线程中 

  66.          * @param result 

  67.          */  

  68.         @Override  

  69.         protected void onPostExecute(Bitmap result) {  

  70.             if (result != null) {  

  71.                 ivPic.setImageBitmap(result);  

  72.                 System.out.println("从网络缓存图片啦.....");  

  73.   

  74.                 //从网络获取图片后,保存至本地缓存  

  75.                 mLocalCacheUtils.setBitmapToLocal(url, result);  

  76.                 //保存至内存中  

  77.                 mMemoryCacheUtils.setBitmapToMemory(url, result);  

  78.   

  79.             }  

  80.         }  

  81.     }  

  82.     /** 

  83.      * AsyncTask就是对handler和线程池的封装 

  84.      * 第一个泛型:参数类型 

  85.      * 第二个泛型:更新进度的泛型 

  86.      * 第三个泛型:onPostExecute的返回结果 

  87.      */  

  88.     @SuppressLint("NewApi")  

  89.     class BitmapTask_view extends AsyncTask<Object, Void, Bitmap> {  

  90.   

  91.         private View ivPic;  

  92.         private String url;  

  93.   

  94.         /** 

  95.          * 后台耗时操作,存在于子线程中 

  96.          * @param params 

  97.          * @return 

  98.          */  

  99.         @Override  

  100.         protected Bitmap doInBackground(Object[] params) {  

  101.             ivPic = (View) params[0];  

  102.             url = (String) params[1];  

  103.   

  104.             return downLoadBitmap(url);  

  105.         }  

  106.   

  107.         /** 

  108.          * 更新进度,在主线程中 

  109.          * @param values 

  110.          */  

  111.         @Override  

  112.         protected void onProgressUpdate(Void[] values) {  

  113.             super.onProgressUpdate(values);  

  114.         }  

  115.   

  116.         /** 

  117.          * 耗时方法结束后执行该方法,主线程中 

  118.          * @param result 

  119.          */  

  120.         @Override  

  121.         protected void onPostExecute(Bitmap result) {  

  122.             if (result != null) {  

  123.                 //ivPic.setImageBitmap(result);  

  124.                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {    

  125.                     //Android系统大于等于API16,使用setBackground    

  126.                     ivPic.setBackground(new BitmapDrawable(result));  

  127.                 } else {    

  128.                     //Android系统小于API16,使用setBackground    

  129.                     ivPic.setBackgroundDrawable(new BitmapDrawable(result));  

  130.                 }    

  131.                   

  132.                   

  133.                 System.out.println("从网络缓存图片啦.....");  

  134.   

  135.                 //从网络获取图片后,保存至本地缓存  

  136.                 mLocalCacheUtils.setBitmapToLocal(url, result);  

  137.                 //保存至内存中  

  138.                 mMemoryCacheUtils.setBitmapToMemory(url, result);  

  139.   

  140.             }  

  141.         }  

  142.     }  

  143.     /** 

  144.      * 网络下载图片 

  145.      * @param url 

  146.      * @return 

  147.      */  

  148.     public Bitmap downLoadBitmap(String url) {  

  149.         HttpURLConnection conn = null;  

  150.         try {  

  151.             conn = (HttpURLConnection) new URL(url).openConnection();  

  152.             conn.setConnectTimeout(5000);  

  153.             conn.setReadTimeout(5000);  

  154.             conn.setRequestMethod("GET");  

  155.   

  156.             int responseCode = conn.getResponseCode();  

  157.             if (responseCode == 200) {  

  158.                 //图片压缩  

  159.                 BitmapFactory.Options options = new BitmapFactory.Options();  

  160.                 options.inSampleSize=2;//宽高压缩为原来的1/2  

  161.                 options.inPreferredConfig=Bitmap.Config.ARGB_4444;  

  162.                   

  163.                 //Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(),null,options);  

  164.                 Bitmap bitmap=BitmapFactory.decodeStream(conn.getInputStream());  

  165.                 return bitmap;  

  166.             }  

  167.         } catch (IOException e) {  

  168.             e.printStackTrace();  

  169.         }catch (Exception e) {  

  170.         } finally {  

  171.             if(conn!=null){  

  172.                 conn.disconnect();  

  173.             }  

  174.         }  

  175.   

  176.         return null;  

  177.     }  

  178. }  

 2.4外部写一个bitmapUtils来调用它们。

  1. public class MyBitmapUtils {  

  2.     private NetCacheUtils mNetCacheUtils;  

  3.     private LocalCacheUtils mLocalCacheUtils;  

  4.     private MemoryCacheUtils mMemoryCacheUtils;  

  5.   

  6.     public MyBitmapUtils(){  

  7.         mMemoryCacheUtils=new MemoryCacheUtils();  

  8.         mLocalCacheUtils=new LocalCacheUtils();  

  9.         mNetCacheUtils=new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils);  

  10.     }  

  11.     public Bitmap getBitmap(String url){  

  12.         Bitmap bitmap=null;  

  13.          bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);  

  14.         if(bitmap!=null){  

  15.             return bitmap;  

  16.         }  

  17.         bitmap = mLocalCacheUtils.getBitmapFromLocal(url);  

  18.         if(bitmap!=null){  

  19.              mMemoryCacheUtils.setBitmapToMemory(url,bitmap);  

  20.              return bitmap;  

  21.         }  

  22.           

  23.          return bitmap;  

  24.     }  

  25.     public void disPlay(ImageView ivPic, String url) {  

  26.         Bitmap bitmap;  

  27.         //内存缓存  

  28.         bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);  

  29.         if (bitmap!=null){  

  30.             ivPic.setImageBitmap(bitmap);  

  31.            Log.d("iamgecache","从内存获取图片啦.....--->"+url);  

  32.             return;  

  33.         }  

  34.   

  35.         //本地缓存  

  36.         bitmap = mLocalCacheUtils.getBitmapFromLocal(url);  

  37.         if(bitmap !=null){  

  38.             ivPic.setImageBitmap(bitmap);  

  39.             Log.d("iamgecache","从本地获取图片啦.....-->"+url);  

  40.             //从本地获取图片后,保存至内存中  

  41.             mMemoryCacheUtils.setBitmapToMemory(url,bitmap);  

  42.             return;  

  43.         }  

  44.         //网络缓存  

  45.         mNetCacheUtils.getBitmapFromNet(ivPic,url);  

  46.         Log.d("iamgecache","从网络获取图片啦.....-->"+url);  

  47.     }  

  48.       

  49.       

  50.     @SuppressLint("NewApi")  

  51.     public void disPlay(View ivPic, String url) {  

  52.         Bitmap bitmap;  

  53.         //内存缓存  

  54.         bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);  

  55.         if (bitmap!=null){  

  56.             //ivPic.setImageBitmap(bitmap);  

  57.             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {    

  58.                 //Android系统大于等于API16,使用setBackground    

  59.                 ivPic.setBackground(new BitmapDrawable(bitmap));  

  60.             } else {    

  61.                 //Android系统小于API16,使用setBackground    

  62.                 ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap));  

  63.                  

  64.             }    

  65.             //ivPic.setBackground(new BitmapDrawable(bitmap));  

  66.              

  67.             Log.d("iamgecache","从内存获取图片啦.....--->"+url);  

  68.             return;  

  69.         }  

  70.   

  71.         //本地缓存  

  72.         bitmap = mLocalCacheUtils.getBitmapFromLocal(url);  

  73.         if(bitmap !=null){  

  74.         //    ivPic.setImageBitmap(bitmap);  

  75.               

  76.             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {    

  77.                 //Android系统大于等于API16,使用setBackground    

  78.                 ivPic.setBackground(new BitmapDrawable(bitmap));  

  79.             } else {    

  80.                 //Android系统小于API16,使用setBackground    

  81.                 ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap));  

  82.             }    

  83.             //ivPic.setBackground(new BitmapDrawable(bitmap));  

  84.              

  85.               

  86.             Log.d("iamgecache","从本地获取图片啦.....-->"+url);  

  87.             //从本地获取图片后,保存至内存中  

  88.             mMemoryCacheUtils.setBitmapToMemory(url,bitmap);  

  89.             return;  

  90.         }  

  91.         //网络缓存  

  92.         mNetCacheUtils.getBitmapFromNet(ivPic,url);  

  93.       //  ivPic.setBackground(new BitmapDrawable(bitmap));  

  94.         Log.d("iamgecache","从网络获取图片啦.....-->"+url);  

  95.     }  

  96. }  

      个人封装的网络缓存框架的好处是便于修改,自己清楚流程。适合于一些对图片质量没那么高要求而又需要缓存减少网络访问的情景。

原文出处

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP