Android图片三级缓存策略

1.简介

Android缓存原理都是一样,可以自己封装。

三级缓存:

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

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

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

2.实现步骤

2.1 内存缓存:

[java] view plain copy
public class MemoryCacheUtils {
private LruCache<String,Bitmap> mMemoryCache;
public MemoryCacheUtils(){
long maxMemory = Runtime.getRuntime().maxMemory()/8;//得到手机最大允许内存的1/8,即超过指定内存,则开始回收
//需要传入允许的内存最大值,虚拟机默认内存16M,真机不一定相同
mMemoryCache=new LruCache<String,Bitmap>((int) maxMemory){
//用于计算每个条目的大小
@Override
protected int sizeOf(String key, Bitmap value) {
int byteCount = value.getByteCount();
return byteCount;
}
};
}
/**

  • 从内存中读图片
  • @param url
    /
    public Bitmap getBitmapFromMemory(String url) {
    //Bitmap bitmap = mMemoryCache.get(url);//1.强引用方法
    /
    2.弱引用方法
    SoftReference<Bitmap> bitmapSoftReference = mMemoryCache.get(url);
    if (bitmapSoftReference != null) {
    Bitmap bitmap = bitmapSoftReference.get();
    return bitmap;
    }
    */
    if(url==null||"".equals(url)){
    return null;
    }
    Bitmap bitmap = mMemoryCache.get(url);
      return bitmap;  

    }
    /**

  • 往内存中写图片
  • @param url
  • @param bitmap
    /
    public void setBitmapToMemory(String url, Bitmap bitmap) {
    //mMemoryCache.put(url, bitmap);//1.强引用方法
    /
    2.弱引用方法
    mMemoryCache.put(url, new SoftReference<>(bitmap));
    */
    mMemoryCache.put(url,bitmap);
    }
    }
    2.2本地缓存

[java] view plain copy
public class LocalCacheUtils {
private static final String CACHE_PATH= Environment.getExternalStorageDirectory().getAbsolutePath()+"/my/images";
/**

  • 从本地读取图片
  • @param url
    */
    public Bitmap getBitmapFromLocal(String url){
    String fileName = null;//把图片的url当做文件名,并进行MD5加密
    try {
    fileName = MD5Encoder.encode(url); //这里加不加密无所谓
    File file=new File(CACHE_PATH,fileName);
    Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(file));
    return bitmap;
    } catch (Exception e) {
    e.printStackTrace();
    }
    return null;
    }

    /**

  • 从网络获取图片后,保存至本地缓存
  • @param url
  • @param bitmap
    */
    public void setBitmapToLocal(String url,Bitmap bitmap){
    try {
         String fileName = MD5Encoder.encode(url);//把图片的url当做文件名,并进行MD5加密
         File file=new File(CACHE_PATH,fileName);  
    
         //通过得到文件的父文件,判断父文件是否存在
         File parentFile = file.getParentFile();
         if (!parentFile.exists()){
             parentFile.mkdirs();
         }
         //把图片保存至本地
         bitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(file));
     } catch (Exception e) {
         e.printStackTrace();
     }  

    }
    }
    2.3网络缓存

[java] view plain copy
public class NetCacheUtils {
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;

public NetCacheUtils(LocalCacheUtils localCacheUtils, MemoryCacheUtils memoryCacheUtils) {
    mLocalCacheUtils = localCacheUtils;
    mMemoryCacheUtils = memoryCacheUtils;
}
public NetCacheUtils(){  

}
/**
 * 从网络下载图片
 * @param ivPic 显示图片的imageview
 * @param url   下载图片的网络地址
 */
public void getBitmapFromNet(ImageView ivPic, String url) {
    new BitmapTask().execute(ivPic, url);//启动AsyncTask  

}  

public void getBitmapFromNet(View ivPic, String url) {
    new BitmapTask_view().execute(ivPic, url);//启动AsyncTask  

}
public Bitmap getBitmapFromNet(final String url) {
    //启动AsyncTask
    return null;
}
/**
 * AsyncTask就是对handler和线程池的封装
 * 第一个泛型:参数类型
 * 第二个泛型:更新进度的泛型
 * 第三个泛型:onPostExecute的返回结果
 */
class BitmapTask extends AsyncTask<Object, Void, Bitmap> {  

    private ImageView ivPic;
    private String url;  

    /**
     * 后台耗时操作,存在于子线程中
     * @param params
     * @return
     */
    @Override
    protected Bitmap doInBackground(Object[] params) {
        ivPic = (ImageView) params[0];
        url = (String) params[1];  

        return downLoadBitmap(url);
    }  

    /**
     * 更新进度,在主线程中
     * @param values
     */
    @Override
    protected void onProgressUpdate(Void[] values) {
        super.onProgressUpdate(values);
    }  

    /**
     * 耗时方法结束后执行该方法,主线程中
     * @param result
     */
    @Override
    protected void onPostExecute(Bitmap result) {
        if (result != null) {
            ivPic.setImageBitmap(result);
            System.out.println("从网络缓存图片啦.....");  

            //从网络获取图片后,保存至本地缓存
            mLocalCacheUtils.setBitmapToLocal(url, result);
            //保存至内存中
            mMemoryCacheUtils.setBitmapToMemory(url, result);  

        }
    }
}
/**
 * AsyncTask就是对handler和线程池的封装
 * 第一个泛型:参数类型
 * 第二个泛型:更新进度的泛型
 * 第三个泛型:onPostExecute的返回结果
 */
@SuppressLint("NewApi")
class BitmapTask_view extends AsyncTask<Object, Void, Bitmap> {  

    private View ivPic;
    private String url;  

    /**
     * 后台耗时操作,存在于子线程中
     * @param params
     * @return
     */
    @Override
    protected Bitmap doInBackground(Object[] params) {
        ivPic = (View) params[0];
        url = (String) params[1];  

        return downLoadBitmap(url);
    }  

    /**
     * 更新进度,在主线程中
     * @param values
     */
    @Override
    protected void onProgressUpdate(Void[] values) {
        super.onProgressUpdate(values);
    }  

    /**
     * 耗时方法结束后执行该方法,主线程中
     * @param result
     */
    @Override
    protected void onPostExecute(Bitmap result) {
        if (result != null) {
            //ivPic.setImageBitmap(result);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                //Android系统大于等于API16,使用setBackground
                ivPic.setBackground(new BitmapDrawable(result));
            } else {
                //Android系统小于API16,使用setBackground
                ivPic.setBackgroundDrawable(new BitmapDrawable(result));
            }    

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

            //从网络获取图片后,保存至本地缓存
            mLocalCacheUtils.setBitmapToLocal(url, result);
            //保存至内存中
            mMemoryCacheUtils.setBitmapToMemory(url, result);  

        }
    }
}
/**
 * 网络下载图片
 * @param url
 * @return
 */
public Bitmap downLoadBitmap(String url) {
    HttpURLConnection conn = null;
    try {
        conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setConnectTimeout(5000);
        conn.setReadTimeout(5000);
        conn.setRequestMethod("GET");  

        int responseCode = conn.getResponseCode();
        if (responseCode == 200) {
            //图片压缩
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize=2;//宽高压缩为原来的1/2
            options.inPreferredConfig=Bitmap.Config.ARGB_4444;  

            //Bitmap bitmap = BitmapFactory.decodeStream(conn.getInputStream(),null,options);
            Bitmap bitmap=BitmapFactory.decodeStream(conn.getInputStream());
            return bitmap;
        }
    } catch (IOException e) {
        e.printStackTrace();
    }catch (Exception e) {
    } finally {
        if(conn!=null){
            conn.disconnect();
        }
    }  

    return null;
}  

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

[java] view plain copy
public class MyBitmapUtils {
private NetCacheUtils mNetCacheUtils;
private LocalCacheUtils mLocalCacheUtils;
private MemoryCacheUtils mMemoryCacheUtils;

public MyBitmapUtils(){
    mMemoryCacheUtils=new MemoryCacheUtils();
    mLocalCacheUtils=new LocalCacheUtils();
    mNetCacheUtils=new NetCacheUtils(mLocalCacheUtils,mMemoryCacheUtils);
}
public Bitmap getBitmap(String url){
    Bitmap bitmap=null;
     bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);
    if(bitmap!=null){
        return bitmap;
    }
    bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
    if(bitmap!=null){
         mMemoryCacheUtils.setBitmapToMemory(url,bitmap);
         return bitmap;
    }  

     return bitmap;
}
public void disPlay(ImageView ivPic, String url) {
    Bitmap bitmap;
    //内存缓存
    bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);
    if (bitmap!=null){
        ivPic.setImageBitmap(bitmap);
       Log.d("iamgecache","从内存获取图片啦.....--->"+url);
        return;
    }  

    //本地缓存
    bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
    if(bitmap !=null){
        ivPic.setImageBitmap(bitmap);
        Log.d("iamgecache","从本地获取图片啦.....-->"+url);
        //从本地获取图片后,保存至内存中
        mMemoryCacheUtils.setBitmapToMemory(url,bitmap);
        return;
    }
    //网络缓存
    mNetCacheUtils.getBitmapFromNet(ivPic,url);
    Log.d("iamgecache","从网络获取图片啦.....-->"+url);
}  

@SuppressLint("NewApi")
public void disPlay(View ivPic, String url) {
    Bitmap bitmap;
    //内存缓存
    bitmap=mMemoryCacheUtils.getBitmapFromMemory(url);
    if (bitmap!=null){
        //ivPic.setImageBitmap(bitmap);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            //Android系统大于等于API16,使用setBackground
            ivPic.setBackground(new BitmapDrawable(bitmap));
        } else {
            //Android系统小于API16,使用setBackground
            ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap));  

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

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

    //本地缓存
    bitmap = mLocalCacheUtils.getBitmapFromLocal(url);
    if(bitmap !=null){
    //    ivPic.setImageBitmap(bitmap);  

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            //Android系统大于等于API16,使用setBackground
            ivPic.setBackground(new BitmapDrawable(bitmap));
        } else {
            //Android系统小于API16,使用setBackground
            ivPic.setBackgroundDrawable(new BitmapDrawable(bitmap));
        }
        //ivPic.setBackground(new BitmapDrawable(bitmap));  

        Log.d("iamgecache","从本地获取图片啦.....-->"+url);
        //从本地获取图片后,保存至内存中
        mMemoryCacheUtils.setBitmapToMemory(url,bitmap);
        return;
    }
    //网络缓存
    mNetCacheUtils.getBitmapFromNet(ivPic,url);
  //  ivPic.setBackground(new BitmapDrawable(bitmap));
    Log.d("iamgecache","从网络获取图片啦....-->"+url);
}  

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

原文地址:http://blog.51cto.com/13797975/2126664

时间: 2024-10-13 17:00:17

Android图片三级缓存策略的相关文章

Android 图片三级缓存加载框架原理解析与代码实现

本文主要介绍三级缓存的原理解析与实现方式.以前一直觉得三级缓存图片加载是一个很难理解的东西,但是自己看了一下午再试着写了一遍之后感觉还是只要沉下心思考还时很容易熟悉掌握的. 所谓三级缓存:首先是内存-文件(外存)-网络三级缓存机制. 首先: 框架需要一个接入方法NGImageloadHelper.java: /** * 图片加载框架使用帮助类 * Created by nangua on 2016/7/8. */ public class NGImageloadHelper { /** * 处理

Android开发中图片的三级缓存策略

一.简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好.所以一个应用的图片缓存策略是很重要的.通常情况下,Android应用程序中图片的缓存策略采用"内存-本地-网络"三级缓存策略,首先应用程序访问网络拉取图片,分别将加载的图片保存在本地SD卡中和内存中,当程序再一次需要加载图片的时候,先判断内存中是否有缓存,有则直接从内存中拉取,否则查看本地SD卡中是否有缓存,SD

Android中图片的三级缓存策略

一.简介 现在的Android应用程序中,不可避免的都会使用到图片,如果每次加载图片的时候都要从网络重新拉取,这样不但很耗费用户的流量,而且图片加载的也会很慢,用户体验很不好.所以一个应用的图片缓存策略是很重要的.通常情况下,Android应用程序中图片的缓存策略采用"内存-本地-网络"三级缓存策略,首先应用程序访问网络拉取图片,分别将加载的图片保存在本地SD卡中和内存中,当程序再一次需要加载图片的时候,先判断内存中是否有缓存,有则直接从内存中拉取,否则查看本地SD卡中是否有缓存,SD

Android实战——RxJava2解锁图片三级缓存框架

RxJava2解锁图片三级缓存框架 本篇文章包括以下内容 前言 图片三级缓存的介绍 框架结构目录的介绍 构建项目整体框架 实现图片三级缓存 演示效果 源码下载 结语 前言 RxJava2作为如今那么主流的技术,不学习学习都不行了,本篇文章需要你有RxJava2的基础,如果需要对RxJava2学习的同学,可以关注我的博客,查看Android实战--RxJava2+Retrofit+RxBinding解锁各种新姿势 .项目代码实现模仿Picasso,大伙们可以看下最后的代码效果,那么废话不多说,He

毕加索的艺术——Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选

毕加索的艺术--Picasso,一个强大的Android图片下载缓存库,OkHttpUtils的使用,二次封装PicassoUtils实现微信精选 官网: http://square.github.io/picasso/ 我们在上篇OkHttp的时候说过这个Picasso,学名毕加索,是Square公司开源的一个Android图形缓存库,而且使用起来也是非常的简单,只要一行代码就轻松搞定了,你会问,为什么不介绍一下Glide?其实Glide我有时间也是会介绍的,刚好上篇我们用到了Picasso,

基于Java LinkedList,实现Android大数据缓存策略

import java.util.HashMap; import java.util.LinkedList; /* * 基于Java LinkedList,实现Android大数据缓存策略 * 作者:Zhang Phil * 原文出处:http://blog.csdn.net/zhangphil * * 实现原理:原理的模型认为:在LinkedList的头部元素是最旧的缓存数据,在LinkedList的尾部是最新的缓存数据. * 在一个LinkedList(类型C的链表)维护一个存储堆栈,添加元

属性动画与图片三级缓存

属性动画 动画: UI渐变, 变量值的变化 ObjectAnimator : ofInt("backgroundColor",start,end); ValueAnimator: for(int i = start; i< end; i++) { a = i; } ValueAnimator animation=ValueAnimator.ofInt(start,end); animation.setDuration(DURATION); animation.addUpdateL

图片三级缓存的原理

三级缓存的概念: 内存-->硬盘-->网络 由内存.硬盘.网络缓存形成. 关于三级缓存用到的技术: Android高效加载大图.多图解决方案.有效避免程序OOM使用的核心技术就是LruCache. LruCache只是管理了内存中图片的存储与释放,如果图片从内存中被移除的话,那么又需要从网络上重新加载一次图片,这显然非常耗时.对此,Google又提供了一套硬盘缓存的解决方案:DiskLruCache(非Google官方编写,但获得官方认证. 用法和流程: 当每次加载图片的时候都优先去内存加载图

android bitmap的缓存策略

在这篇文章中: lrucache disklrucache 缓存策略对比与总结 不论是android还是ios设备,流量对于用户而言都是宝贵的.在没有wifi的场景下,如果加载批量的图片消耗用户过多流量,被其知晓,又要被念叨一波~ 如何避免消耗过多的流量呢?当程序第一次从网络加载图片后,就将其缓存到移动设备上,这样再次使用这个图片时,就不用再次从网络上下载为用户节省了流量. 目前常用的一种缓存算法是lru(least recently used),它的核心思想是当缓存满了,会优先淘汰近期最少使用