【android】实现图片的三级缓存。工具类

来源:互联网 发布:ip网络功放链接 编辑:程序博客网 时间:2024/06/06 12:33

本文主要分析以下几点

  • 为什么使用三级缓存
  • 什么是三级缓存
  • 三级缓存原理
  • 代码的具体实现:有注释
  • 工具类使用方法
  • github分享地址

1、为什么使用三级缓存

  • 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了
  • 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响
  • 特别是,当我们想要重复浏览一些图片时,如果每一次浏览都需要通过网络获取,流量的浪费可想而知
  • 因此提出三级缓存策略,通过网络、本地、内存三级缓存图片,来减少不必要的网络交互,避免浪费流量

2、什么是三级缓存

  • 网络缓存, 不优先加载, 速度慢,浪费流量
  • 本地缓存, 次优先加载, 速度快
  • 内存缓存, 优先加载, 速度最快

3、三级缓存原理

  • 首次加载 Android App 时,肯定要通过网络交互来获取图片,之后我们可以将图片保存至本地SD卡和内存中
  • 之后运行 App 时,优先访问内存中的图片缓存,若内存中没有,则加载本地SD卡中的图片
  • 总之,只在初次访问新内容时,才通过网络获取图片资源

4、代码的具体实现:有注释

  • 图片缓存工具类
/** * 图片加载工具类(三级缓存) * <p> * 注意: * 1.首次加载 Android App 时,肯定要通过网络交互来获取图片,之后我们可以将图片保存至本地SD卡和内存中 * 2.之后运行 App 时,优先访问内存中的图片缓存,若内存中没有,则加载本地SD卡中的图片 * 3.总之,只在初次访问新内容时,才通过网络获取图片资源 * Created by zxp on 2016/6/17. */public class ImageLoaderUtils {    private static volatile ImageLoaderUtils imageLoaderUtils;    private MenoryCacheUtils menoryCacheUtils;//内存缓存    private LocalCacheUtils localCacheUtils;//本地缓存    private NetBitmapUtils netBitmapUtils;//网络加载    //单例模式    public static ImageLoaderUtils getInstance() {        if (null == imageLoaderUtils) {            synchronized (ImageLoaderUtils.class) {                if (null == imageLoaderUtils) {                    imageLoaderUtils = new ImageLoaderUtils();                }            }        }        return imageLoaderUtils;    }    /**     * 加载图片     *     * @param imageView 图片视图     * @param url       图片地址     */    public void setImageViewFromBitmap(ImageView imageView, String url) {        setImageViewFromBitmap(imageView, url, NetBitmapUtils.BITMAP_INSAMPLESIZE_ONE);    }    /**     * 加载图片     *     * @param imageView      图片视图     * @param url            图片地址     * @param compressNumber 压缩倍率     */    public void setImageViewFromBitmap(ImageView imageView, String url, int compressNumber) {        if (menoryCacheUtils == null) {            menoryCacheUtils = new MenoryCacheUtils();        }        if (localCacheUtils == null) {            localCacheUtils = new LocalCacheUtils();        }        if (netBitmapUtils == null) {            netBitmapUtils = new NetBitmapUtils(menoryCacheUtils, localCacheUtils);        }        Bitmap bitmap;        //从内存缓存        bitmap = menoryCacheUtils.getBitmap(url);        if (bitmap != null) {            setImageView(imageView, bitmap);            return;        }        //本地缓存        bitmap = localCacheUtils.getBitmap(url);        if (bitmap != null) {            setImageView(imageView, bitmap);            menoryCacheUtils.saveBitmap(url, bitmap);            return;        }        //网络获取        netBitmapUtils.getBitmap(imageView, url, compressNumber);    }    //设置图片    private void setImageView(ImageView imageView, Bitmap bitmap) {        imageView.setImageBitmap(bitmap);    }}
  • 内存缓存工具类
/** * 内存缓存 * Created by zxp on 2016/6/17. */public class MenoryCacheUtils {    private LruCache<String, Bitmap> lruCache;    public MenoryCacheUtils() {        //通常得到手机最大内存的1/8,如果app在使用过程中超过这个,会自动回收        long maxMenory = Runtime.getRuntime().maxMemory() / 8;        lruCache = new LruCache<String, Bitmap>((int) maxMenory) {            @Override            protected int sizeOf(String key, Bitmap value) {                return value.getByteCount();            }        };    }    /**     * 写入图片到内存     *     * @param url    地址     * @param bitmap 图片     */    public void saveBitmap(String url, Bitmap bitmap) {        lruCache.put(url, bitmap);    }    /**     * 从内存中拿到图片     *     * @param url 地址     */    public Bitmap getBitmap(String url) {        return lruCache.get(url);    }}
  • 本地缓存工具类
/** * 本地缓存工具类 * Created by zxp on 2016/6/17. */public class LocalCacheUtils {    //文件村粗的路径    private static final String CACHE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath() +            "/ImageCache";    /**     * 拿到本地存储的图片     *     * @param url 地址     * @return     */    public Bitmap getBitmap(String url) {        try {            //截取文件名字            String fileName = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));            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 saveBitmap(String url, Bitmap bitmap) {        try {            String fileName = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf("."));            File file = new File(CACHE_PATH, fileName);            //判断父目录是否存在,不存在新建一个            File parentFile = file.getParentFile();            if (!parentFile.exists()) {                parentFile.mkdirs();            }            //保存图片到本地,            // 注意第二个参数:如果不压缩是100,表示压缩率为0,如果是30,表示压缩70%;            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file));        } catch (Exception e) {            e.printStackTrace();        }    }}
  • 网路加载工具类
** * 网络加载图片工具类 * 网络请求拿到的结果数据bitmap,再保存在本地和内存中 * Created by zxp on 2016/6/17. */public class NetBitmapUtils {    public static final int BITMAP_INSAMPLESIZE_ONE = 1;//原图    public static final int BITMAP_INSAMPLESIZE_HALF = 2;//宽高变为1/2    public static final int BITMAP_INSAMPLESIZE_ONE_THIRD = 3;//宽高变为1/3    public static final int BITMAP_INSAMPLESIZE_ONE_QUARTER = 4;//宽高变为1/4    private LocalCacheUtils localCacheUtils;    private MenoryCacheUtils menoryCacheUtils;    //图片压缩倍率(比如:1为不压缩,2为压缩宽高为一半)    private int compressNumber = 1;    public NetBitmapUtils(MenoryCacheUtils menoryCacheUtils, LocalCacheUtils localCacheUtils) {        this.menoryCacheUtils = menoryCacheUtils;        this.localCacheUtils = localCacheUtils;    }    public NetBitmapUtils(MenoryCacheUtils menoryCacheUtils, LocalCacheUtils localCacheUtils, int compressNumber) {        this.menoryCacheUtils = menoryCacheUtils;        this.localCacheUtils = localCacheUtils;        this.compressNumber = compressNumber;    }    /**     * 网络下载图片     *     * @param iv  显示图片的imagview     * @param url 网络下载的地址     */    public void getBitmap(ImageView iv, String url) {        getBitmap(iv, url, compressNumber);    }    /**     * 网络下载图片     *     * @param iv             显示图片的imagview     * @param url            网络下载的地址     * @param compressnumber 图片压缩倍率(1为不压缩)     */    public void getBitmap(ImageView iv, String url, int compressnumber) {        this.compressNumber = compressnumber;        new ImageViewTask().execute(iv, url, compressnumber);    }    /**     * AsyncTask就是对handler和线程池的封装     * 第一个泛型:参数类型     * 第二个泛型:更新进度的泛型     * 第三个泛型:onPostExecute的返回结果     */    class ImageViewTask extends AsyncTask<Object, Void, Bitmap> {        private ImageView iv;        private String url;        private int compressNumber;        //在后台做耗时操作,运行在子线程        @Override        protected Bitmap doInBackground(Object... params) {            iv = (ImageView) params[0];            url = (String) params[1];            compressNumber = (int) params[2];            return downloadBitmap(url);        }        //更新进步,在主线程        @Override        protected void onProgressUpdate(Void... values) {            super.onProgressUpdate(values);        }        //耗时方法(请求网络)结束后执行该方法,在主线程中,带有请求结果的返回值        @Override        protected void onPostExecute(Bitmap bitmap) {            if (bitmap != null) {                iv.setImageBitmap(bitmap);                //网络拿到的图片保存到本地                localCacheUtils.saveBitmap(url, bitmap);                //网络拿到的图片保存到内存中                menoryCacheUtils.saveBitmap(url, bitmap);            }        }        private Bitmap downloadBitmap(String url) {            HttpURLConnection connection = null;            try {                connection = (HttpURLConnection) new URL(url).openConnection();                connection.setConnectTimeout(3000);                connection.setReadTimeout(3000);                connection.setRequestMethod("GET");                //请求成功                if (connection.getResponseCode() == 200) {                    BitmapFactory.Options options = new BitmapFactory.Options();                    //图片压缩                    if (compressNumber > 1) {                        //如果compressNumber为2,宽高压缩为原来的1/2                        options.inSampleSize = compressNumber;                    }                    //ALPHA_8——代表8位Alpha位图                    //ARGB_4444——代表16位ARGB位图                    //ARGB_8888——代表32位ARGB位图                    //RGB_565——代表8位RGB位图                    options.inPreferredConfig = Bitmap.Config.ARGB_4444;                    Bitmap bitmap = BitmapFactory.decodeStream(connection.getInputStream(), null, options);                    return bitmap;                }            } catch (Exception e) {                e.printStackTrace();            }            return null;        }    }}

工具类使用方法

ImageLoaderUtils.getInstance().setImageViewFromBitmap(imageView , url);

图片宽高压缩为原来一半:
ImageLoaderUtils.getInstance().setImageViewFromBitmap(imageView , url , 2);


github分享地址

github的Demo

0 0
原创粉丝点击