通常我们说的三级缓存是指Memory,Disk,NetWork,因为我们都知道从网络读取一条数据往往存在各种因素速度不尽人意,如果一个应用中任何数据都是实时从网络获取,那么我们想象一下用户每次都要面对如进度条转个两三圈才显示数据这种体验肯定是不佳的,所以我们需要缓存数据,所以本文介绍使用RxJava通过实例来讲解如何缓存数据。
定义一个数据实体类,简单的定义了一个数据内容,以及一个时间用来代表缓存时长。
public class CacheData {
private static final int CACHE_TIME = 5000;
public String data;
public long time;
public CacheData(String value) {
this.data = value;
time = System.currentTimeMillis();
}
public boolean isUpToData() {
return System.currentTimeMillis() - time >= CACHE_TIME;
}
}
定义Memory,Disk,NetWork三个缓存的Observable:
public class Source {
/**
* 内存缓存
*/
CacheData memery;
/**
* 硬盘缓存
*/
CacheData disk;
/**
* 网络获取数据
*/
int requestData;
public Source() {
Timber.tag("Source");
}
/**
* 从内存里读取缓存
*/
public Observable<CacheData> getFromMemory() {
Observable<CacheData> observable = Observable.create(new Observable.OnSubscribe<CacheData>() {
@Override
public void call(Subscriber<? super CacheData> subscriber) {
subscriber.onNext(memery);
subscriber.onCompleted();
}
});
return observable.compose(getFrom("MEMORY"));
}
/**
* 从硬盘中读取缓存
*/
public Observable<CacheData> getFromDisk() {
Observable<CacheData> observable = Observable.create(new Observable.OnSubscribe<CacheData>() {
@Override
public void call(Subscriber<? super CacheData> subscriber) {
subscriber.onNext(disk);
subscriber.onCompleted();
}
});
return observable.compose(getFrom("DISK"));
}
/**
* 从网络中读取数据
*/
public Observable<CacheData> getFromNet() {
Observable<CacheData> observable = Observable.create(new Observable.OnSubscribe<CacheData>() {
@Override
public void call(Subscriber<? super CacheData> subscriber) {
requestData ++;
subscriber.onNext(new CacheData("Data is = " + requestData));
subscriber.onCompleted();
}
});
return observable.doOnNext(new Action1<CacheData>() {
@Override
public void call(CacheData cacheData) {
memery = cacheData;
disk = cacheData;
}
}).compose(getFrom("NETWORK"));
}
/**
* Transformer转换 判断数据的状态
*/
private Observable.Transformer<CacheData, CacheData> getFrom( final String source) {
Observable.Transformer<CacheData, CacheData> loadFromTransformer = new Observable.Transformer<CacheData, CacheData>() {
@Override
public Observable<CacheData> call(Observable<CacheData> cacheDataObservable) {
return cacheDataObservable.doOnNext(new Action1<CacheData>() {
@Override
public void call(CacheData cacheData) {
if (cacheData == null) {
Timber.e(source + " --- cacheData is null check again ---");
} else if (cacheData.isUpToData()) {
Timber.e(source + " --- cacheData is out of time ---");
} else {
Timber.e(source + " --- cacheData you gotta ---");
}
}
});
}
};
return loadFromTransformer;
}
}
代码中我们分别定义了memory、disk缓存并且我们定义了一个requestData用来假设是网络数据。其中的memory和disk的Observable比较好理解就是发射对应的缓存就好,我们主要讲里面一些涉及的操作符。
doOnNext:标示当Observable在调用onNext发射数据的时候会调用到这里面,然后我们可以通过自定义一个Action把里面的数据缓存到memory和disk中去。
observable.doOnNext(new Action1<CacheData>() {
@Override
public void call(CacheData cacheData) {
memery = cacheData;
disk = cacheData;
}
})
Observable.Transformer:转换操作可以将源Observable通过不断他链式的结构能直接作用于Observable上去,常见于复用操作符等操作,这里我们通过使用它来打印数据是从哪里取出来的。
Observable.Transformer<CacheData, CacheData> loadFromTransformer = new Observable.Transformer<CacheData, CacheData>() {
@Override
public Observable<CacheData> call(Observable<CacheData> cacheDataObservable) {
return cacheDataObservable.doOnNext(new Action1<CacheData>() {
@Override
public void call(CacheData cacheData) {
if (cacheData == null) {
Timber.e(source + " --- cacheData is null check again ---");
} else if (cacheData.isUpToData()) {
Timber.e(source + " --- cacheData is out of time ---");
} else {
Timber.e(source + " --- cacheData you gotta ---");
}
}
});
}
};
Ok,万事都准备好了 那么我们调用起来看看效果喽。
Source source = new Source();
observable = Observable.concat(source.getFromMemory(), source.getFromDisk(), source.getFromNet())
.first(new Func1<CacheData, Boolean>() {
@Override
public Boolean call(CacheData cacheData) {
return null != cacheData && !cacheData.isUpToData();
}
});
这里又涉及了两个操作符
concat:保证顺序的组合操作,这样一次从memory、disk、network中去数据。
first:取Observable中的第一个数据,我们这里自己定义了一个Func函数标示说取满足条件的第一个数据。
解释完了,我们使用subscribe订阅这个Observable:
observable.subscribe(new Action1() {
@Override
public void call(Object o) {
Timber.i("Result = " + ((CacheData) o).data);
}
});
最后我们看看效果。
MEMORY --- cacheData is null check again ---
DISK --- cacheData is null check again ---
NETWORK --- cacheData you gotta ---
I/MainActivity: Result = Data is = 1
MEMORY --- cacheData you gotta ---
I/MainActivity: Result = Data is = 1
我们可以看出第一次调用的时候 数据来自网络,第二次调用就来自内存了,符合我们的三级缓存的效果。
Thanks:http://blog.chinaunix.net/uid-20771867-id-5145681.html