一、概述:

现在android应用中不可避免的要使用图片,有些图片是可以变化的,需要每次启动时从网络拉取,这种场景在有广告位的应用以及纯图片应用(比如百度美拍)中比较多。

现在有一个问题:假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量。在当前的状况下,对于非wifi用户来说,流量还是很贵的,一个很耗流量的应用,其用户数量级肯定要受到影响。当然,我想,向百度美拍这样的应用,必然也有其内部的图片缓存策略。总之,图片缓存是很重要而且是必须的。

二、实现原理:

实现图片缓存也不难,需要有相应的cache策略。这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且也把它划到缓存的层次结构中。当根据url向网络拉取图片的时候,先从内存中找,如果内存中没有,再从缓存文件中查找,如果缓存文件中也没有,再从网络上通过http请求拉取图片。在键值对(key-value)中,这个图片缓存的key是图片url的hash值,value就是bitmap。所以,按照这个逻辑,只要一个url被下载过,其图片就被缓存起来了。

但这里不使用SoftReference,而使用LruCache进行图片的缓存
为什么使用LruCache:
这个类非常适合用来缓存图片,它的主要算法原理是把最近使用的对象用强引用存储在 LinkedHashMap 中,并且把最近最少使用的对象在缓存值达到预设定值之前从内存中移除。

在过去,我们经常会使用一种非常流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。但是现在已经不再推荐使用这种方式了,因为从 Android 2.3 (API Level 9)开始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存当中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃。

三、具体实现:

1)在构造方法里初始化LruCache mCache

if (mCache == null) {// 最大使用的内存空间int maxSize = (int) (Runtime.getRuntime().freeMemory() / 4);mCache = new LruCache<String, Bitmap>(maxSize) {@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getRowBytes() * value.getHeight();}};}

2)去内存中取

Bitmap bitmap = mCache.get(url);if (bitmap != null) {// 直接显示iv.setImageBitmap(bitmap);return;}

3)去硬盘上取

bitmap = loadBitmapFromLocal(url);if (bitmap != null) {// 直接显示iv.setImageBitmap(bitmap);return;}

4)从网络加载

loadBitmapFromNet(iv, url);

四、详细代码:

/*** @项目名: 3G缓存加载图片* @包名: com.android.news.tools* @类名: ImageHelper* @创建者: chen.lin* @创建时间: 2015-4-27 上午10:50:37* */
public class ImageHelper {// 内存缓存池// private Map<String, SoftReference<Bitmap>> mCache = new// LinkedHashMap<String, SoftReference<Bitmap>>();// LRUCahce 池子private static LruCache<String, Bitmap> mCache;private static Handler mHandler;private static ExecutorService mThreadPool;private static Map<ImageView, Future<?>> mTaskTags = new LinkedHashMap<ImageView, Future<?>>();private Context mContext;public ImageHelper(Context context) {this.mContext = context;if (mCache == null) {// 最大使用的内存空间int maxSize = (int) (Runtime.getRuntime().freeMemory() / 4);mCache = new LruCache<String, Bitmap>(maxSize) {@Overrideprotected int sizeOf(String key, Bitmap value) {return value.getRowBytes() * value.getHeight();}};}if (mHandler == null) {mHandler = new Handler();}if (mThreadPool == null) {// 最多同时允许的线程数为3个mThreadPool = Executors.newFixedThreadPool(3);}}public void display(ImageView iv, String url) {// 1.去内存中取Bitmap bitmap = mCache.get(url);if (bitmap != null) {// 直接显示iv.setImageBitmap(bitmap);return;}// 2.去硬盘上取bitmap = loadBitmapFromLocal(url);if (bitmap != null) {// 直接显示iv.setImageBitmap(bitmap);return;}// 3. 去网络获取图片loadBitmapFromNet(iv, url);}private void loadBitmapFromNet(ImageView iv, String url) {// 开线程去网络获取// 使用线程池管理// new Thread(new ImageLoadTask(iv, url)).start();// 判断是否有线程在为 imageView加载数据Future<?> futrue = mTaskTags.get(iv);if (futrue != null && !futrue.isCancelled() && !futrue.isDone()) {System.out.println("取消 任务");// 线程正在执行futrue.cancel(true);futrue = null;}// mThreadPool.execute(new ImageLoadTask(iv, url));futrue = mThreadPool.submit(new ImageLoadTask(iv, url));// Future 和 callback/Runable// 返回值,持有正在执行的线程// 保存mTaskTags.put(iv, futrue);System.out.println("标记 任务");}class ImageLoadTask implements Runnable {private String mUrl;private ImageView iv;public ImageLoadTask(ImageView iv, String url) {this.mUrl = url;this.iv = iv;}@Overridepublic void run() {// HttpUrlconnectiontry {// 获取连接HttpURLConnection conn = (HttpURLConnection) new URL(mUrl).openConnection();conn.setConnectTimeout(30 * 1000);// 设置连接服务器超时时间conn.setReadTimeout(30 * 1000);// 设置读取响应超时时间// 连接网络conn.connect();// 获取响应码int code = conn.getResponseCode();if (200 == code) {InputStream is = conn.getInputStream();// 将流转换为bitmapBitmap bitmap = BitmapFactory.decodeStream(is);// 存储到本地write2Local(mUrl, bitmap);// 存储到内存mCache.put(mUrl, bitmap);// 图片显示:不可取// iv.setImageBitmap(bitmap);mHandler.post(new Runnable() {@Overridepublic void run() {// iv.setImageBitmap(bitmap);display(iv, mUrl);}});}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}/*** 本地种去去图片* * @param url*/private Bitmap loadBitmapFromLocal(String url) {// 去找文件,将文件转换为bitmapString name;try {name = MD5Encoder.encode(url);File file = new File(getCacheDir(), name);if (file.exists()) {Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());// 存储到内存mCache.put(url, bitmap);return bitmap;}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}private void write2Local(String url, Bitmap bitmap) {String name;FileOutputStream fos = null;try {name = MD5Encoder.encode(url);File file = new File(getCacheDir(), name);fos = new FileOutputStream(file);// 将图像写到流中bitmap.compress(CompressFormat.JPEG, 100, fos);} catch (Exception e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();fos = null;} catch (IOException e) {e.printStackTrace();}}}}private String getCacheDir() {String state = Environment.getExternalStorageState();File dir = null;if (Environment.MEDIA_MOUNTED.equals(state)) {// 有sd卡dir = new File(Environment.getExternalStorageDirectory(), "/Android/data/" + mContext.getPackageName()+ "/icon");} else {// 没有sd卡dir = new File(mContext.getCacheDir(), "/icon");}if (!dir.exists()) {dir.mkdirs();}return dir.getAbsolutePath();}
}

五、使用方法:

在Adapter 的getView方法里

ImageView iv = (contentView)findViewById(R.id.iv);
String url = "http://localhost:8080/web/1.jpg";
new IamgeHelper(this).display(iv,url);

———————————————————————
有需求者请加qq:136137465,非诚勿扰
(java 架构师全套教程,共760G, 让你从零到架构师,每月轻松拿3万)
01.高级架构师四十二个阶段高
02.Java高级系统培训架构课程148课时
03.Java高级互联网架构师课程
04.Java互联网架构Netty、Nio、Mina等-视频教程
05.Java高级架构设计2016整理-视频教程
06.架构师基础、高级片
07.Java架构师必修linux运维系列课程
08.Java高级系统培训架构课程116课时
(送:hadoop系列教程,java设计模式与数据结构, Spring Cloud微服务, SpringBoot入门)
——————————————————————–

Android 使用三级缓存实现对图片的加载相关推荐

  1. java加载图片到缓存_Android实现图片异步加载并缓存到本地

    在android应用开发的时候,加载网络图片是一个非常重要的部分,很多图片不可能放在本地,所以就必须要从服务器或者网络读取图片. 软引用是一个现在非常流行的方法,用户体验比较好,不用每次都需要从网络下 ...

  2. android webView的缓存机制和资源预加载

    android 原生使用WebView嵌入H5页面 Hybrid开发 一.性能问题 android webview 里H5加载速度慢 网络流量大 1.H5页面加载速度慢 渲染速度慢 js解析效率 js ...

  3. ListView中的图片异步加载、缓存

    一.ListView的图片异步加载 我们都知道对每一个Weibo Item都有用户头像,而且每一条微博还可能带有图片.如果在加载列表的同时加载图片,这样有几个缺点,第一很费事,界面卡住,用户体验很不好 ...

  4. android复位机器人图片_Universal-Image-Loader 图片异步加载类库还不熟?

    码个蛋(codeegg) 第 824 次推文 作者:欢醉 博客:https://cloud.tencent.com/developer/article/1026386 码妞看世界 写在前面 这个图片异 ...

  5. Android 图片异步加载的体会,SoftReference已经不再适用

    在网络上搜索Android图片异步加载的相关文章,目前大部分提到的解决方案,都是采用Map<String, SoftReference<Drawable>>  这样软引用的方式 ...

  6. android webview 图片异步加载,Webview 图片异步加载及bug解决

    在项目中新闻显示需要使用图片的异步加载,并且在加载图片前和加载图片失败时显示默认图片. 关于webview中图片的异步加载的思路如下: 方案一:由前端同学全权负责(使用js实现异步加载) 方案二:an ...

  7. android图片异步加载图片,Android 异步加载图片分析总结

    研究了android从网络上异步加载图像,现总结如下: (1)由于android UI更新支持单一线程原则,所以从网络上取数据并更新到界面上,为了不阻塞主线程首先可能会想到以下方法. 在主线程中new ...

  8. Android图片的加载与压缩

    目录 图片加载 图片压缩 Bitmap(位图)的压缩 色位深度 图片文件与Bitmap 压缩--位图读取 压缩--位图写入 对compress的使用反思 注意事项 图片加载 在了解图片压缩前,先简单介 ...

  9. android图片获取加载小结

    获取方式 1.内存 内存缓存主要使用LRU缓存算法,引用support-v4中的LruCache, 通过键值对的形式获取到相应的bitmap,配置如下: //初始化缓存策略int maxMem = ( ...

  10. 图片预加载的问题-----有针对加载和缓存的兼容解决

    网站开发时经常需要在某个页面需要实现对大量图片的浏览,如果考虑流量的话,大可以像pconline一样每个页面只显示一张图片,让用户每看一张图片就需要重新下载一下整个页面.不过,在web2.0时代,更多 ...

最新文章

  1. SLAM的通用框架:GSLAM
  2. python中的引用、浅拷贝和深拷贝
  3. SpringBoot--HelloWord
  4. win10安装java1.8开发环境JDK
  5. 孝敬父母 天经地义 |有人这么疑问?
  6. 阿里大数据分析与应用(part5)--QuickBI
  7. codeforces F.Fibonacci String Subsequences
  8. 卸载VMware Server后,无法加载登录用户界面 #F#
  9. 不均衡数据集采样1——SMOTE算法(过采样)
  10. vbs if 不等于_(四)if 判断与逻辑运算符
  11. 学习网络编程第一步,安装NetAssist网络调试助手
  12. 医学影像后处理服务器系统架构是,医学影像系统(PACS)
  13. 有测试智商的软件不,测试智商的软件有哪些
  14. 看完这篇文章,保你学会C语言 :for 循环
  15. Java 密码学算法
  16. (原)Ubuntu16中编译caffe
  17. Java里面的四种内存屏障
  18. numpy中mgrid()和meshgrid()函数
  19. android+蓝牙体温计,一种蓝牙体温计的制作方法
  20. 网站建设入门技术导航

热门文章

  1. linux 统一设备模型 pci,【原创】Linux PCI驱动框架分析(二)
  2. 本人的月末结账步骤备忘
  3. noip2018提高组广东省成绩
  4. 地图坐标转换-火星坐标
  5. Web3 赋能音乐行业,能否创造更多价值?
  6. 数模论文写作方法2|摘要的技巧
  7. 如何进入华为云服务器,【华为云入门】如何快速创建弹性云服务器
  8. Android studio emulator Terminated
  9. Xilinx HLS 学习笔记1
  10. 栈溢出学习(四)之Hijack GOT