硅谷新闻9--图片三级缓存

1.三级缓存设计步骤:

* 从内存中取图片
* 从本地文件中取图片
     向内存中保持一份
* 请求网络图片,获取图片,显示到控件上
     向内存存一份
     向本地文件中存一份

 1 package com.atguigu.beijingnews.utils;
 2 
 3 import android.graphics.Bitmap;
 4 import android.os.Handler;
 5 
 6 public class BitmapCacheUtils {
 7 
 8     /**
 9      * 网络缓存工具类
10      */
11     private NetCacheUtils netCacheUtils;
12 
13     /**
14      * 本地缓存工具类
15      */
16 
17     private LocalCacheUtils localCacheUtils;
18 
19     /**
20      内存缓存工具类
21      */
22     private MemoryCacheUtils memoryCacheUtils;
23 
24     public BitmapCacheUtils(Handler handler) {
25         memoryCacheUtils = new MemoryCacheUtils();
26         localCacheUtils = new LocalCacheUtils(memoryCacheUtils);
27         netCacheUtils = new NetCacheUtils(handler,localCacheUtils,memoryCacheUtils);
28 
29     }
30 
31 
32     /**
33      * 三级缓存设计步骤:
34      *   * 从内存中取图片
35      *   * 从本地文件中取图片
36      *        向内存中保持一份
37      *   * 请求网络图片,获取图片,显示到控件上,Hanlder,postion
38      *      * 向内存存一份
39      *      * 向本地文件中存一份
40      *
41      * @param imageUrl
42      * @param position
43      * @return
44      */
45     public Bitmap getBitmap(String imageUrl, int position) {
46         //1.从内存中取图片
47         if (memoryCacheUtils != null) {
48             Bitmap bitmap = memoryCacheUtils.getBitmapFromUrl(imageUrl);
49             if (bitmap != null) {
50                 LogUtil.e("内存加载图片成功=="+position);
51                 return bitmap;
52             }
53         }
54 
55         //2.从本地文件中取图片
56         if (localCacheUtils != null) {
57             Bitmap bitmap = localCacheUtils.getBitmapFromUrl(imageUrl);
58             if (bitmap != null) {
59                 LogUtil.e("本地加载图片成功=="+position);
60                 return bitmap;
61             }
62         }
63 
64         //3.请求网络图片
65         netCacheUtils.getBitmapFomNet(imageUrl, position);
66         return null;
67     }
68 }
BitmapCacheUtils

2.网络缓存

线程池类Executors的使用

public static ExecutorService newCachedThreadPool()

创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。

public static ExecutorService newFixedThreadPool(int nThreads)

创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。

 1 package com.atguigu.beijingnews.utils;
 2 
 3 import android.graphics.Bitmap;
 4 import android.graphics.BitmapFactory;
 5 import android.os.Handler;
 6 import android.os.Message;
 7 
 8 import java.io.IOException;
 9 import java.io.InputStream;
10 import java.net.HttpURLConnection;
11 import java.net.URL;
12 import java.util.concurrent.ExecutorService;
13 import java.util.concurrent.Executors;
14 
15 public class NetCacheUtils {
16 
17     /**
18      * 请求图片成功
19      */
20     public static final int SUCESS = 1;
21     /**
22      * 请求图片失败
23      */
24     public static final int FAIL = 2;
25     private final Handler handler;
26     /**
27      * 本地缓存工具类
28      */
29     private final LocalCacheUtils localCacheUtils;
30     /**
31      * 内存缓存工具类
32      */
33     private final MemoryCacheUtils memoryCacheUtils;
34     /**
35      * 线程池类
36      */
37     private  ExecutorService service;
38 
39     public NetCacheUtils(Handler handler, LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {
40         this.handler = handler;
41         service = Executors.newFixedThreadPool(10);
42         this.localCacheUtils = localCacheUtils;
43         this.memoryCacheUtils =memoryCacheUtils;
44     }
45 
46     //联网请求得到图片
47     public void getBitmapFomNet(String imageUrl, int position) {
48 //        new Thread(new MyRunnable(imageUrl,position)).start();
49         service.execute(new MyRunnable(imageUrl,position));
50     }
51 
52     class MyRunnable implements  Runnable{
53 
54         private final String imageUrl;
55         private final int position;
56 
57         public MyRunnable(String imageUrl, int position) {
58             this.imageUrl = imageUrl;
59             this.position = position;
60         }
61 
62         @Override
63         public void run() {
64             //子线程
65             //请求网络图片
66             try {
67                 URL urL = new URL(imageUrl);
68                 HttpURLConnection connection = (HttpURLConnection) urL.openConnection();
69                 connection.setRequestMethod("GET");//只能大写
70                 connection.setConnectTimeout(4000);
71                 connection.setReadTimeout(4000);
72                 connection.connect();//可写可不写
73                 int code = connection.getResponseCode();
74                 if(code ==200){
75                     InputStream is = connection.getInputStream();
76                     Bitmap bitmap = BitmapFactory.decodeStream(is);
77 
78                     //显示到控件上,发消息吧Bitmap发出去和position
79                     Message msg = Message.obtain();
80                     msg.what = SUCESS;
81                     msg.arg1 = position;
82                     msg.obj = bitmap;
83                     handler.sendMessage(msg);
84 
85                     //在内存中缓存一份
86                     memoryCacheUtils.putBitmap(imageUrl,bitmap);
87                     //在本地中缓存一份
88                     localCacheUtils.putBitmap(imageUrl,bitmap);
89                 }
90             } catch (IOException e) {
91                 e.printStackTrace();
92                 Message msg = Message.obtain();
93                 msg.what = FAIL;
94                 msg.arg1 = position;
95                 handler.sendMessage(msg);
96             }
97         }
98     }
99 }
NetCacheUtils

3.本地缓存

File file = new File(CACHE_DIR, fileName);  FileInputStream FileOutputStream 文件读写方式

演示把图片移除后,在查看
C:UsersAdministrator>adb shell
# cd /mnt/sdcard/atguigu_beijingnews
cd /mnt/sdcard/atguigu_beijingnews
# rm *
rm *

 1 package com.atguigu.beijingnews.utils;
 2 
 3 import android.graphics.Bitmap;
 4 import android.graphics.BitmapFactory;
 5 import android.os.Environment;
 6 
 7 import java.io.File;
 8 import java.io.FileInputStream;
 9 import java.io.FileOutputStream;
10 
11 public class LocalCacheUtils {
12     private final MemoryCacheUtils memoryCacheUtils;
13 
14     public LocalCacheUtils(MemoryCacheUtils memoryCacheUtils) {
15         this.memoryCacheUtils = memoryCacheUtils;
16     }
17 
18     /**
19      * 根据Url获取图片
20      * @param imageUrl
21      * @return
22      */
23     public Bitmap getBitmapFromUrl(String imageUrl) {
24         //判断sdcard是否挂载
25         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
26             //保存图片在/mnt/sdcard/beijingnews/http://192.168.21.165:8080/xsxxxx.png
27             //保存图片在/mnt/sdcard/beijingnews/llkskljskljklsjklsllsl
28             try {
29                 String fileName = MD5Encoder.encode(imageUrl);//llkskljskljklsjklsllsl
30 
31                 ///mnt/sdcard/beijingnews/llkskljskljklsjklsllsl
32                 File file = new File(Environment.getExternalStorageDirectory()+"/beijingnews",fileName);
33 
34 
35 
36 
37                 if(file.exists()){
38 
39                     FileInputStream is = new FileInputStream(file);
40                     Bitmap bitmap = BitmapFactory.decodeStream(is);
41                     if(bitmap != null){
42                         memoryCacheUtils.putBitmap(imageUrl,bitmap);
43                         LogUtil.e("把从本地保持到内存中");
44                     }
45                     return  bitmap;
46 
47                 }
48 
49             } catch (Exception e) {
50                 e.printStackTrace();
51                 LogUtil.e("图片获取失败");
52             }
53         }
54 
55         return null;
56     }
57 
58     /**
59      * 根据Url保存图片
60      * @param imageUrl url
61      * @param bitmap 图片
62      */
63     public void putBitmap(String imageUrl, Bitmap bitmap) {
64 
65         //判断sdcard是否挂载
66         if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
67             //保存图片在/mnt/sdcard/beijingnews/http://192.168.21.165:8080/xsxxxx.png
68             //保存图片在/mnt/sdcard/beijingnews/llkskljskljklsjklsllsl
69             try {
70                 String fileName = MD5Encoder.encode(imageUrl);//llkskljskljklsjklsllsl
71 
72                 ///mnt/sdcard/beijingnews/llkskljskljklsjklsllsl
73                 File file = new File(Environment.getExternalStorageDirectory()+"/beijingnews",fileName);
74 
75                 File parentFile =  file.getParentFile();//mnt/sdcard/beijingnews
76                 if(!parentFile.exists()){
77                     //创建目录
78                     parentFile.mkdirs();
79                 }
80 
81 
82                 if(!file.exists()){
83                     file.createNewFile();
84                 }
85                 //保存图片
86                 bitmap.compress(Bitmap.CompressFormat.PNG,100,new FileOutputStream(file));
87 
88             } catch (Exception e) {
89                 e.printStackTrace();
90                 LogUtil.e("图片本地缓存失败");
91             }
92         }
93 
94 
95     }
96 }
LocalCacheUtils

4.内存缓存

引用级别

我们经常会使用一种非常流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。
但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象;

另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,

这就有潜在的风险造成应用程序的内存溢出并崩溃。所以看到还有很多相关文章还在推荐用软引用或弱引用 (SoftReference or WeakReference),就有点out了

Android3.0后提出新的方式
LruCache 缓存的集合,把常用的数据,保留起来,把不常用的给回收。
Lru近期最少使用算法

 1 package com.atguigu.beijingnews.utils;
 2 
 3 import android.graphics.Bitmap;
 4 
 5 import org.xutils.cache.LruCache;
 6 
 7 /**
 8  * 作用:Java之软引用&弱引用&虚引用
 9  */
10 public class MemoryCacheUtils {
11 
12     /**
13      * 集合
14      */
15     private LruCache<String,Bitmap> lruCache;
16 
17     public MemoryCacheUtils(){
18         //使用了系统分配给应用程序的八分之一内存来作为缓存大小
19         int maxSize = (int) (Runtime.getRuntime().maxMemory()/1024/8);
20         lruCache = new LruCache<String,Bitmap>(maxSize){
21             @Override
22             protected int sizeOf(String key, Bitmap value) {
23 //                return super.sizeOf(key, value);
24                 return (value.getRowBytes() * value.getHeight())/1024;
25             }
26         };
27     }
28 
29     /**
30      * 根据url从内存中获取图片
31      * @param imageUrl
32      * @return
33      */
34     public Bitmap getBitmapFromUrl(String imageUrl) {
35         return lruCache.get(imageUrl);
36     }
37 
38     /**
39      * 根据url保存图片到lruCache集合中
40      * @param imageUrl 图片路径
41      * @param bitmap 图片
42      */
43     public void putBitmap(String imageUrl, Bitmap bitmap) {
44         lruCache.put(imageUrl,bitmap);
45     }
46 }
MemoryCacheUtils
原文地址:https://www.cnblogs.com/ganchuanpu/p/6014510.html