Universal-image-loader数据接口和缓存实现策略

本文探讨了Android中图片数据的缓存策略,包括网络缓存、磁盘缓存和内存缓存,详细介绍了Universal-image-loader的缓存机制,如BaseImageDownloader和各种缓存策略,如LruMemoryCache、LimitedAgeDiskCache等,旨在提高数据处理速度和用户体验。

数据缓存

图片数据的起始位置是远端的 数据服务器 ,直到被加载到内存中才可以展示到客户端界面的View上。为了加快数据处理速度,需要在每一步对处理过的数据进行保存,再次需要时直接使用节省时间,是为缓存。

数据缓存.png

缓存策略

数据缓存需要提供合适的缓存策略,原因有二:

  1. 空间是有限的:APP分配到的内存大小和在文件系统中占据的空间大小依赖于操作系统的策略,都是有限的;
  2. 空间不足时,需要对现有的数据进行删除,数据被再次用到的几率和频次是不同的;
缓存分类

依据上面的图,按照缓存的位置不同可以分为下面几个:

  1. 网络缓存:也可以称为云缓存,一般需要从云服务运营商处购买服务,例如:CDN;
  2. 磁盘缓存:从云端下载文件到本地文件系统,保存在文件系统中;
  3. 内存缓存:数据在使用前需要加载到内存中,相对文件系统内存空间更小;

图中还有一个部分 客户端网络框架,通常网络框架也会提供文件系统缓存和内存缓存,但是他们本质上是在同一个APP运行实例中,内存和文件系统空间是共享的,没有必要同时使用,这里要注意做好处理。

缓存工具

下面每个部分都有一些工具,例如 BaseImageDownloaderBaseImageDecoder 在框架中起到重要的连接作用,同时也可以作为独立的工具类提供图片数据下载和加载服务。

文件缓存

加载到文件系统

image.png

  • BaseImageDownloader

    Universal-image-loader提供 BaseImageDownloader 支持把多种数据来源的图片资源转存到缓存目录中:

    private boolean downloadImage() throws IOException {
       // 获取数据流
       InputStream is = getDownloader().getStream(uri, options.getExtraForDownloader());
       if (is == null) {
          L.e(ERROR_NO_IMAGE_STREAM, memoryCacheKey);
          return false;
       } else {
          try {
             // 保存到缓存目录
             return configuration.diskCache.save(uri, is, this);
          } finally {
             IoUtils.closeSilently(is);
          }
       }
    } 
    
    @Override
    public InputStream getStream(String imageUri, Object extra) throws IOException {
       switch (Scheme.ofUri(imageUri)) {
          case HTTP:
          case HTTPS:
             return getStreamFromNetwork(imageUri, extra);
          case FILE:
             return getStreamFromFile(imageUri, extra);
          case CONTENT:
             return getStreamFromContent(imageUri, extra);
          case ASSETS:
             return getStreamFromAssets(imageUri, extra);
          case DRAWABLE:
             return getStreamFromDrawable(imageUri, extra);
          case UNKNOWN:
          default:
             return getStreamFromOtherSource(imageUri, extra);
       }
    } 
    
  • BaseImageDownloader扩展

    BaseImageDownloader为每种资源类型提供了接口

    获取Http/Https数据使用的java api提供的网络接口 HttpURLConnection, 如果需要使用其他网络框架例如Okhttp,可以继承 BaseImageDownloader 重新实现 getStreamFromNetwork(), 并为 ImageLoaderConfiguration#downloader 设置一个实例即可。

文件系统缓存策略

文件缓存的类图结构比较简单,提供了两类缓存 无限容量缓存有限容量缓存 。为容量控制提供了两种回收机制。

  1. LimitedAgeDiskCache: 通过缓存时间控制缓存空间回收。
  2. LruDiskCache:使用最近最少使用算法,控制缓存空间回收。

Universal-Image-loader框架默认使用UnlimitedDistCache:ImageLoaderConfiguration#diskCache

image.png

内存缓存

加载到内存

ImageLoaderConfiguration#decoder 提供的默认值是 BaseImageDecoder,图片处理参数 decodingOptions 来自配置参数 DisplayImageOptions#decodingOptions

image.png

内存缓存策略

image.png

上图为MemoryCache模块的类图,橙色区域为核心部分。框架运行时使用的内存缓存策略由ImageLoaderConfiguration#memoryCache参数指定,默认使用:LruMemoryCache

  • 两个基础方案

    1. LruMemoryCache: 带有容量控制的LinkedHashMap结构,设置 accessOrder = true,回收策略使用的是最近最少使用。
    2. WeakMemoryCache: 无容量限制的同步HashMap,Bitmap数据使用 弱引用 方式持有图片数据。
  • LimitedMemoryCache 扩展方案

    LimitedMemoryCache 是一组带有容量控制的同步HashMap,Bitmap数据使用 弱引用 方式持有图片数据,总体效果是对 WeakMemoryCache 添加了容量控制的基础上,在空间不足时给定不同的回收策略。这一组类,因为需要给定不同的回收策略,都增加了额外的存储空间,用于辅助查找下一条优先被回收的数据。

    1. FIFOLimitedMemoryCache:先入先出,即队列。当剩余空间不足时,优先回收队头的数据。
    2. LRULimitedMemoryCache:最近最少使用,LinkedHashMap设置 accessOrder = true,计算空间不足时下一条将要被回收的数据。与 LruMemoryCache 算法一致。
    3. UsingFreqLimitedMemoryCache:最少使用,usingCounts 记录每个数据使用的次数,当空间不足时,最少被使用的数据将会被回收。
    4. LargestLimitedMemoryCache: 最大先出,valueSizes 记录每个数据的大小,当空间不足时,占用空间最大的将会被回收。
  • 两个包装类

    1. LimitedAgeMemoryCache:额外增加“时长”控制逻辑,设定最大保存时间(秒数),在取数据时判断是否缓存超过最大允许时间范围,超过就删除。
    2. FuzzyKeyMemoryCache:设置一个 Comparator 实例,在添加数据前,把满足算法的数据删除,然后插入新的数据。

,设定最大保存时间(秒数),在取数据时判断是否缓存超过最大允许时间范围,超过就删除。
2. FuzzyKeyMemoryCache:设置一个 Comparator 实例,在添加数据前,把满足算法的数据删除,然后插入新的数据。

最后

按照国际惯例,给大家分享一套十分好用的Android进阶资料:《全网最全Android开发笔记》。

整个笔记一共8大模块、729个知识点,3382页,66万字,可以说覆盖了当下Android开发最前沿的技术点,和阿里、腾讯、字节等等大厂面试看重的技术。

图片

图片

因为所包含的内容足够多,所以,这份笔记不仅仅可以用来当学习资料,还可以当工具书用。

如果你需要了解某个知识点,不管是Shift+F 搜索,还是按目录进行检索,都能用最快的速度找到你要的内容。

相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照整个知识体系编排的。

(一)架构师必备Java基础

1、深入理解Java泛型

2、注解深入浅出

3、并发编程

4、数据传输与序列化

5、Java虚拟机原理

6、高效IO

……

图片

(二)设计思想解读开源框架

1、热修复设计

2、插件化框架设计

3、组件化框架设计

4、图片加载框架

5、网络访问框架设计

6、RXJava响应式编程框架设计

……

图片

(三)360°全方位性能优化

1、设计思想与代码质量优化

2、程序性能优化

  • 启动速度与执行效率优化
  • 布局检测与优化
  • 内存优化
  • 耗电优化
  • 网络传输与数据储存优化
  • APK大小优化

3、开发效率优化

  • 分布式版本控制系统Git
  • 自动化构建系统Gradle

……

图片

(四)Android框架体系架构

1、高级UI晋升

2、Android内核组件

3、大型项目必备IPC

4、数据持久与序列化

5、Framework内核解析

……

图片

(五)NDK模块开发

1、NDK开发之C/C++入门

2、JNI模块开发

3、Linux编程

4、底层图片处理

5、音视频开发

6、机器学习

……

图片

(六)Flutter学习进阶

1、Flutter跨平台开发概述

2、Windows中Flutter开发环境搭建

3、编写你的第一个Flutter APP

4、Flutter Dart语言系统入门

……

图片

(七)微信小程序开发

1、小程序概述及入门

2、小程序UI开发

3、API操作

4、购物商场项目实战

……

图片

(八)kotlin从入门到精通

1、准备开始

2、基础

3、类和对象

4、函数和lambda表达式

5、其他

……

图片

好啦,这份资料就给大家介绍到这了,有需要详细文档的小伙伴,可以微信扫下方二维码免费领取哈~

图片

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值