本文主要分析以下几点

  • 为什么使用三级缓存
  • 什么是三级缓存
  • 三级缓存原理
  • 代码的具体实现:有注释
  • 工具类使用方法
  • 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) {@Overrideprotected 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/2public static final int BITMAP_INSAMPLESIZE_ONE_THIRD = 3;//宽高变为1/3public static final int BITMAP_INSAMPLESIZE_ONE_QUARTER = 4;//宽高变为1/4private 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;//在后台做耗时操作,运行在子线程@Overrideprotected Bitmap doInBackground(Object... params) {iv = (ImageView) params[0];url = (String) params[1];compressNumber = (int) params[2];return downloadBitmap(url);}//更新进步,在主线程@Overrideprotected void onProgressUpdate(Void... values) {super.onProgressUpdate(values);}//耗时方法(请求网络)结束后执行该方法,在主线程中,带有请求结果的返回值@Overrideprotected 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/2options.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

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

  1. Android 系统(173)---Android中图片的三级缓存

    Android中图片的三级缓存 为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量 ...

  2. android picasso 三级缓存,Android中图片的三级缓存浅析

    图片的三级缓存机制一般是指应用加载图片的时候,分别去访问内存,文件和网络而获取图片数据的一种行为.以下内容只是简单的介绍了三级缓存的思想和大致流程,还有很多细节未进行处理,如果想深入研究可以在Gith ...

  3. android三级缓存封装,Android 中图片的三级缓存详解

    图片的三级缓存机制一般是指应用加载图片的时候,分别去访问内存,文件和网络而获取图片数据的一种行为. 一.三级缓存流程图 三级缓存流程图 二.代码框架搭建 这里我仿造Picasso[3]的加载图片代码, ...

  4. Android中图片的三级缓存策略

    在开发过程中,经常会碰到进行请求大量的网络图片的样例.假设处理的不好.非常easy造成oom.对于避免oom的方法,无非就是进行图片的压缩.及时的回收不用的图片.这些看似简单可是处理起来事实上涉及的知 ...

  5. android bitmap图片下载三级缓存

    Google为Android开发提供了一个培训教程,在加载图片一节中提供了示例程序BitmapFun,实现了图片下载.缓存.解析加载的功能,具体分析如下: 1.程序介绍 程序整体结构如上图所示,应用启 ...

  6. Android图片的三级缓存

    图片的三级缓存目的 主要目的是为了节省流量.加快加载速度: 每个 app 都会有大量的网络图片存在,当我们不做处理,每次打开 app 都去加载大量网络图片时,会耗费大量的流量,当网速不好时加载速度很慢 ...

  7. Android 开发人员不得不收集的工具类集合

    RxTools 项目地址:vondear/RxTools  简介:Android 开发人员不得不收集的工具类集合 | 支付宝支付 | 微信支付(统一下单) | 微信分享 | Zip4j 压缩(支持分卷 ...

  8. 缓存工具类MyCacheUtil

    MyCacheUtil.java package com.sunrise.jop.common.util;import java.io.File; import java.sql.Timestamp; ...

  9. Android PermissionUtils:运行时权限工具类及申请权限的正确姿势

    Android PermissionUtils:运行时权限工具类及申请权限的正确姿势 ifadai 关注 2017.06.16 16:22* 字数 318 阅读 3637评论 1喜欢 6 Permis ...

最新文章

  1. php 时间倒计时代码 个人写法 有好的想法的欢迎贴出来分享
  2. 2018/12/07 L1-033 出生年 Java
  3. 图说数据中心新风节能技术
  4. Microsoft SQL Server 2005 安装程序错误解疑
  5. Ubuntu 14.04.5 imx6 开发环境搭建
  6. 自己动手写CPU(7)转移指令的实现
  7. java nginx 例子_Java及nginx实现文件权限控制代码实例
  8. JavaScript获取地址栏中的链接参数
  9. C#全局钩子和局部钩子记录
  10. server2012文件服务器的开始按钮,Windows Server 2012实用技巧集锦
  11. 前端实现成绩管理系统
  12. JavaVM和JNIEnv
  13. 2022电大国家开放大学网上形考任务-国学经典选读(山东)非免费(非答案)
  14. Python之MRO
  15. 最近 火火火 的开源项目
  16. 成为一个大数据大牛需要掌握的知识树
  17. HTMLCSS简单学习,看这篇就够了!
  18. 英国《金融时报》:全力加码早期投资,红杉中国在下一盘怎样的棋?...
  19. 关于蓝牙手环日本TELEC认证流程详解
  20. tushare之“前复权”

热门文章

  1. 双飞翼 html 布局,html--双飞翼布局
  2. A-SPICE认证支持工具V-SPICE的应用方案-第1篇 输出物对应方案
  3. android平板被放弃,彻底凉了?谷歌撤下Android平板官方主页
  4. IEEE 802.15.4学习笔记(1)
  5. 区块链+体育赛事怎么玩?拥有300万用户的格斗迷有话说
  6. LNMP架构(1)——LNMP的基础知识
  7. c语言指针p2等于p1,C语言指针 -- 面试题
  8. 计算机网盘怎么换账号密码,科技教程:百度网盘电脑端怎么切换不同的账号进行登录...
  9. ℃江的开发手册__Android工具篇
  10. 继 Linux 之父之后,独立开发者 Jonathan Blow 再次炮轰 C++ 是可怕的语言