序言
Android的图片缓存框架有很多,在Universal-Image-Loader断更之后,就经常使用Glide和Picasso。基于RxJava2的框架实现一个轻量级的图片缓存(三级缓存),加载图片的流程图如图所示:
结合图所得出的流程大概如下
- 请求加载图片。
- 首先检测内存中是否存在数据,如果存在,显示数据,如果没有数据,则下一步。
- 检测本地文件是否存在数据,如果存在,显示数据,并缓存到内存中,如果不存在,则下一步。
- 请求网络获取网络图片显示数据,并把数据缓存到内存和本地文件中。
- 在本个项目中,我们用到的内存缓存是Android自带的LruCaChe,本地缓存是DiskLruCache,其中后者不是属于Android自带的,附下载地址
- 对于以上两个类不作过多陈述,google一下会出来很多demo
现在,我们开始编写这个简单框架
- 首先,先来确定我们项目的基本骨架的使用
1
RxImageLoader.with(MainActivity.this).load(url).into(image_view);
- 通过with(context)方法创建RxImageLoader的单例,这里使用的是构建者模式创建RxImageLoader的对象。为什么要用构建者模式呢?因为链式调用很简洁易懂,例如OKHttp和Retrofit的创建就是通过构建者Builder创建对象的,额,这是题外话,不做过多讲解。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35static volatile RxImageLoader singleton = null;
private RxImageLoader(){
//定义私有的构造方法,防止外部可以通过new来获取RxImageLoader对象
}
//单例模式
public static RxImageLoader with(Context context) {
if (singleton == null) {
synchronized (RxImageLoader.class) {
if (singleton == null) {
singleton = new Builder(context).build();
}
}
}
return singleton;
}
private RxImageLoader(Builder builder) {
mRequestCreator = new RequestCreator(builder.mContext);
}
//构建者模式
private static class Builder {
private Context mContext;
public Builder(Context context) {
this.mContext = context;
}
public RxImageLoader build() {
return new RxImageLoader(this);
}
} - 再看load方法,注意要返回RxImageLoader对象,否者无法链式调用下面的into方法
1
2
3
4public RxImageLoader load(String url) {
this.mUrl = url;
return singleton;
} - 重头戏来了,into方法。我们要获取来自内存,本地,网络三个数据源的数据,按照顺序获取,任一环节有数据,马上调用下面的方法,所以这里调用RxJava的concat操作符和firstElement()
concat操作符—从concatMap操作我们知道,concat操作符肯定也是有序的,而concat操作符是接收若干个Observables,发射数据是有序的,不会交叉。
firstElement()—和RxJava1的first操作符功能相类似,源Observable产生的结果的第一个提交给订阅者。
接下来,看代码
1 | public void into(final ImageView imageView) { |
5.大概框架已经搭建好,现在就是三个数据源获取的问题,首先我们定义一个抽象类,里面包含两个抽象方法,分别是读数据和些数据的。还有一个getImage方法。为什么用抽象类而不用接口呢,抽象类可以有方法的实现体。
1 | public abstract class DataSourceObservable { |
6.编写三个不同数据源的类实现该抽象类,分别是MemoryDataSourceObservable,DiskDataSourceObservable,NetworkDataSourceObservable。
1 | public class MemoryDataSourceObservable extends DataSourceObservable { |
1 | public class DiskDataSourceObservable extends DataSourceObservable { |
1 | public class NetworkDataSourceObservable extends DataSourceObservable { |
7.写一个数据管理类来管理这三个类
1 | public class RequestCreator { |
需要注意的是我们请求数据成功之后需要执行保存数据到内存和本地的操作,我们可以在返回Observable
具体代码请看项目地址项目地址