zoukankan      html  css  js  c++  java
  • 硅谷新闻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
  • 相关阅读:
    线程池小结(一)
    [转]ViewPager学习笔记(一)——懒加载
    [转]Private Libraries、Referenced Libraries、Dependency Libraries的区别
    关于context你必须知道的一切
    【转】在mac上配置安卓SDK
    【转】HTTP中的长连接和短连接分析
    中间件解析FDMEMTABLE.delta生成SQL的方法
    delphi 中配置文件的使用(*.ini)和TIniFile 用法
    Delphi 字符串加密与解密函数
    Delphi编写的等长加密与解密
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/6014510.html
Copyright © 2011-2022 走看看