[TOC]
## ImageWorker
ImageWorker 主要提供的就是 异步 和 缓存
![](https://img.kancloud.cn/90/9b/909b03517bfc476008590ef5057cbaf3_469x464.png)
### ImageWorker类
这个是加载图片的核心类,建议大家看源代码从这个类看起。它的主要功能是从内存/磁盘缓存中加载图片,或者是从网络上下载。这里第一要使用缓存,第二从网络上下载,必然要使用异步线程,所以这里从类图中大家也可以看到它有两个关联类
BitmapWorkerTask(继承自AsynTask)和ImageCache, 分别用来处理异步和缓存。
ImageWorker提供给外部的主要接口是loadImage方法 - 加载图片,如果内存中有,直接加载。否则使用异步线程(BitmapWorkerTask)后台加载 - 从磁盘或者是网络上下载
~~~
public void loadImage(Object data, ImageView imageView) {}
~~~
### BitmapWorkerTask类
异步处理图片 - 下载并绑定图片
### ImageCache类
图片的缓存处理,这里使用了二级缓存: 内存和磁盘。这里从类图也可以看到它有一个关联类DiskLruCache。
### ImageResizer类
继承自ImageWorker,可能有的童鞋会问ImageWorker不是已经实现异步和缓存了吗,这个类是干嘛的呢?这个主要是根据给定的大小对Image做调整。比如当图片太大时,不能简单的加载到内存,需要做大小调整处理。
这里对它的几个主要接口说明一下:
* setImageSize:设置图片要调整的大小
* calculateInSampleSize: 计算缩放比例 - 根据原图大小和要调整后的大小计算
* decodeSampledBitmapFrom\*\*\*:得到调整大小后的图片,,这里好几个方法,数据源不一样而已,没啥大区别。
### ImageFetcher类
继承自ImageResizer。从网络下载图片。这里要澄清一点,processBitmap在ImageWorker中是一个抽象方法,并没有实现体,在本示例中,是在ImageFetcher中实现的。之所以这样设计,是因为图片的来源是不确定和可变的,有可能从网络下载,有可能从本地数据库获取。
## Universal-Image-Loader
![](https://img.kancloud.cn/6e/a3/6ea3bc91f020bd64998cbed8fea2fed6_1000x745.png)
![](https://img.kancloud.cn/6f/b5/6fb53f92a6631d1842ddbe6561dd76b5_630x1108.png)
## 内存缓存
### LruCache
LinkedHashMap 这个队列到底是由谁来维护的,
![](https://img.kancloud.cn/15/59/15592490eaf8eb1f5bbc1872f433f182_739x390.png)
LinkedHashMap 实际上就是hashMap + link 即map里的每个元素增加了前一个引用 和后一个引用
### 其他内存缓存策略
#### 只使用的是强引用缓存
LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类)
#### 使用强引用和弱引用相结合的缓存
UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
~~~
private final Map<Bitmap, Integer> usingCounts = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
//value为使用次数
~~~
LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
~~~
private final Map<String, Bitmap> lruCache = Collections.synchronizedMap(new LinkedHashMap<String, Bitmap>(INITIAL_CAPACITY, LOAD_FACTOR, true));
~~~
FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
~~~
private final List<Bitmap> queue = Collections.synchronizedList(new LinkedList<Bitmap>());
~~~
LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
~~~
private final Map<Bitmap, Integer> valueSizes = Collections.synchronizedMap(new HashMap<Bitmap, Integer>());
//value为大小
~~~
LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)
~~~
private final Map<String, Long> loadingDates = Collections.synchronizedMap(new HashMap<String, Long>());
//value为时间戳
~~~
#### 只使用弱引用缓存
WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收掉)
## 磁盘缓存
### 获取缓存地址
~~~
public File getDiskCacheDir(Context context, String uniqueName) {
String cachePath;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
|| !Environment.isExternalStorageRemovable()) {
cachePath = context.getExternalCacheDir().getPath();
} else {
cachePath = context.getCacheDir().getPath();
}
return new File(cachePath + File.separator + uniqueName);
~~~
可以看到,当SD卡存在或者SD卡不可被移除的时候,就调用getExternalCacheDir()方法来获取缓存路径,否则就调用getCacheDir()方法来获取缓存路径。前者获取到的就是 /sdcard/Android/data//cache 这个路径,而后者获取到的是 /data/data//cache 这个路径。
### 实际效果
![](https://img.kancloud.cn/72/f6/72f67fdd50e07bfe9a5c6cf2a8948fa3_250x226.png)
缓存目录有许多个文件名很长的文件,和一个journal文件,那个文件名很长的文件自然就是缓存的图片了,因为是使用了MD5编码来进行命名的。
journal记录了操作,作为管理缓存的手段
- Android
- 四大组件
- Activity
- Fragment
- Service
- 序列化
- Handler
- Hander介绍
- MessageQueue详细
- 启动流程
- 系统启动流程
- 应用启动流程
- Activity启动流程
- View
- view绘制
- view事件传递
- choreographer
- LayoutInflater
- UI渲染概念
- Binder
- Binder原理
- Binder最大数据
- Binder小结
- Android组件
- ListView原理
- RecyclerView原理
- SharePreferences
- AsyncTask
- Sqlite
- SQLCipher加密
- 迁移与修复
- Sqlite内核
- Sqlite优化v2
- sqlite索引
- sqlite之wal
- sqlite之锁机制
- 网络
- 基础
- TCP
- HTTP
- HTTP1.1
- HTTP2.0
- HTTPS
- HTTP3.0
- HTTP进化图
- HTTP小结
- 实践
- 网络优化
- Json
- ProtoBuffer
- 断点续传
- 性能
- 卡顿
- 卡顿监控
- ANR
- ANR监控
- 内存
- 内存问题与优化
- 图片内存优化
- 线下内存监控
- 线上内存监控
- 启动优化
- 死锁监控
- 崩溃监控
- 包体积优化
- UI渲染优化
- UI常规优化
- I/O监控
- 电量监控
- 第三方框架
- 网络框架
- Volley
- Okhttp
- 网络框架n问
- OkHttp原理N问
- 设计模式
- EventBus
- Rxjava
- 图片
- ImageWoker
- Gilde的优化
- APT
- 依赖注入
- APT
- ARouter
- ButterKnife
- MMKV
- Jetpack
- 协程
- MVI
- Startup
- DataBinder
- 黑科技
- hook
- 运行期Java-hook技术
- 编译期hook
- ASM
- Transform增量编译
- 运行期Native-hook技术
- 热修复
- 插件化
- AAB
- Shadow
- 虚拟机
- 其他
- UI自动化
- JavaParser
- Android Line
- 编译
- 疑难杂症
- Android11滑动异常
- 方案
- 工业化
- 模块化
- 隐私合规
- 动态化
- 项目管理
- 业务启动优化
- 业务架构设计
- 性能优化case
- 性能优化-排查思路
- 性能优化-现有方案
- 登录
- 搜索
- C++
- NDK入门
- 跨平台
- H5
- Flutter
- Flutter 性能优化
- 数据跨平台