打造自己的Android-Universal-Image-Loader
之前的文章了,一直放在 github 上,打算慢慢都放到简书上来。
最近阅读了Android-Universal-Image-Loader的源码,又正在学习设计模式,就写一个ImageLoader练练手。
大概分为以下几个步骤吧,
-
简述下图片加载器的思路
-
简要介绍一下Android-Universal-Image-Loader源码
-
在阅读源码的基础上搭建我们的ImageLoader架构,其中穿插一些自己对设计模式的理解
-
编码实现
简述图片加载器的思路
个人理解中,项目中使用图片加载器的原因主要是能提高图片加载速度,节省用户流量,防止大图片引发OOM,大部分实现方法就是采用三级缓存,网络加载-内存缓存-磁盘缓存,加载时先在内存缓存中查找,找到直接加载,没有找到再到磁盘缓存中查找,并加载到内存缓存中,如果都没有找到则从网络下载,并缓存到内存和磁盘中。加载到图片后根据实际需要对图片进行处理并展示。这就是图片加载的原理。
简要介绍一下Android-Universal-Image-Loader的实现。
网上有很多关于Android-Universal-Image-Loader源码解析,这里只简要介绍一下。
Android-UIL中最主要的函数就是Imageloader.displayImage();下面流程图显示了整个调用流程
Android-UIL中主要有几个重要的类:
ImageLoader
图片加载等主要调用的类,使用了单例。
主要成员变量
-
ImageLoaderConfiguration configuration; // 保存主要的配置 用了Builder模式
-
ImageLoaderEngine engine; // 用于派发异步任务
-
ImageLoaderListener listener; // 回调监听接口
-
ImageLoader instance; // 单例实例
主要函数
-
init(); // 主要用于初始化ImageLoader, 设置Configuration以及初始化engine
-
displayImage(); // 加载图片并显示到 view 中
-
loadImage(); // 加载图片到缓存中并调用回调接口,并不显示,其最后还是调用了displayImage(),其实最重要的就是displayImage()了,其中主要调用了 ProcessAndDisplayTask 和 LoadAndDisplayTask 的run 函数,具体的加载过程可以看看上面的流程图再结合代码看一下。
ImageLoaderConfiguration
配置信息类,保存了配置信息,用了 Builder 模式
主要成员变量
-
MemoryCache
-
DiskCache
-
ImageDownloader
-
ImageDecoder
-
DisplayImageOptions
等等,可以参考源码看一下,主要是保存之后在ImageLoader中调用
主要函数
*createDefault(); // 返回一个默认的 Builder
ImageLoaderEngine
将任务分发到具体的线程池中
主要成员变量
主要就是三个线程池
-
Executor taskExecutor; // 用于从源获取图片的线程池
-
Executor taskExecutorForCachedImages; // 从缓存池中获取图片的线程池
-
Executor taskDistributor; // 分发任务的线程池,把任务分发到上面两个线程池中
主要函数
- submit(); // 提交任务线程
ProcessAndDisplayTask
处理图片并显示
主要函数
**run(); // 此函数中主要有两个处理步骤,1. 调用BitmapProcessor对bitmap进行处理 2. 调用DisplayBitmapTask 显示图片,主要的逻辑又转移到了DisplayBitmapTask的run函数中。
LoadAndDisplayTask
加载图片并显示
主要函数
- run(); // 先监测memoryCache中是否缓存有图片,有的话直接调用DisplayBitmapTask进行显示,没有的话从diskCache中加载,diskCache中也没有的话就从网络或者其他源进行加载。
DisplayBitmapTask
显示图片
主要函数
- run(); // 直接调用Displayer的display函数,之后调用回调函数listener.onLoadingComplete()
Displayer
显示器接口,
主要函数
- display();
MemoryCache
内存缓存
主要函数
-
put();
-
get();
-
remove();
-
keys();
-
clear();
DiskCache
内存卡缓存
主要函数
-
getDirectory();
-
get();
-
save();
-
remove();
-
close();
-
clear();
ImageDownloader
加载指定源的图片流
主要函数
- getStream();
总结一些用到的设计模式
-
六大设计原则
单一职责
开闭原则
里氏替换
依赖倒置
接口隔离
迪米特法则 -
单例模式
-
Builder模式
-
外观模式
-
工厂模式
设计整体框架
项目目录如下:
下面是各个类的一些主要成员变量和成员函数
ImageLoader
-
ImageConfig
-
ImageEngine
-
ImageLoader instance
-
displayImage()
-
loadImage()
ImageEngine
ThreadPool
- submit()
LoadAndDisplayTask
- run()
DisplayTask
- run()
ImageConfig
Decoder
Loader
Displayer
HttpConnection
ThreadPool
MemoryCache
DiskCache
Builder
ImageConfigFactory
-
getDefaultXXX()
-
Decoder
-
decode()
-
Displayer
-
display()
Loader
- load()