RxCache配合retrofit使用的缓存方案
首先看一下rxcache的官方demo
/**
* 此为RxCache官方Demo
*/
public interface CacheProviders {
@LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES)
Observable<Reply<List<Repo>>> getRepos(Observable<List<Repo>> oRepos, DynamicKey userName, EvictDynamicKey evictDynamicKey);
@LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES)
Observable<Reply<List<User>>> getUsers(Observable<List<User>> oUsers, DynamicKey idLastUserQueried, EvictProvider evictProvider);
Observable<Reply<User>> getCurrentUser(Observable<User> oUser, EvictProvider evictProvider);
}
接下来我们看一下RxCache的初始化
CacheProviders cacheProviders = new RxCache.Builder()
.persistence(cacheDir, new GsonSpeaker())
.using(CacheProviders.class);
关于rxache的一些基本使用请参考下文
https://www.jianshu.com/p/b58ef6b0624b
进入源码之前我们首先思考一下这么几个问题,
1,通过上面的例子我们可以看出rxchace通过注解的方式定义了接口方法,那么它是在什么地方具体实现的
2,既然是缓存,它都有哪些缓存策略
接下来我们进入RxCache类的using方法看下这个方法都干了些什么
下面看下源码
public <T> T using(final Class<T> classProviders) {
proxyProviders = new ProxyProviders(builder, classProviders);
return (T) Proxy.newProxyInstance(
classProviders.getClassLoader(),
new Class<?>[] {classProviders},
proxyProviders);
}
从这里我们可以看出,这里是通过动态代理的方式,返回了一个执行对象,这个对象就是传入的接口的具体实现类。关于不了解动态代码机制的自行研究学习
接下来,我们进入ProxyProviders,ProxyProviders继承InvocationHandler,这个类是动态代理的关键类,主要方法是invoke,进入ivoke方法
@Override public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable {
return Observable.defer(new Callable<ObservableSource<?>>() {
@Override public ObservableSource<?> call() throws Exception {
Observable observable = processorProviders.process(proxyTranslator.processMethod(method, args));
Class<?> methodType = method.getReturnType();
if (methodType == Observable.class) return Observable.just(observable);
if (methodType == Single.class) return Observable.just(Single.fromObservable(observable));
if (methodType == Maybe.class) {
return Observable.just(Maybe.fromSingle(Single.fromObservable(observable)));
}
if (method.getReturnType() == io.reactivex.Flowable.class) {
return Observable.just(observable.toFlowable(BackpressureStrategy.MISSING));
}
String errorMessage = method.getName() + io.rx_cache2.internal.Locale.INVALID_RETURN_TYPE;
throw new RuntimeException(errorMessage);
}
}).blockingFirst();
}
这里关键代码是
Observable observable = processorProviders.process(proxyTranslator.processMethod(method, args));
在这里processorProviders是一个接口,已经在ProxyProviders的构造器里面初始化过。这里的初始化方式是通过Dagger的方式,具体Dagger的使用方式自行研究。最终processorProviders实现类是ProcessorProvidersBehaviour。接下来我们进入ProcessorProvidersBehaviour类的process方法
@Override
public <T> Observable<T> process(final io.rx_cache2.ConfigProvider configProvider) {
return Observable.defer(new Callable<ObservableSource<? extends T>>() {
@Override public ObservableSource<? extends T> call() throws Exception {
if (hasProcessesEnded) {
return getData(configProvider);
}
return oProcesses.flatMap(new Function<Integer, ObservableSource<? extends T>>() {
@Override public ObservableSource<? extends T> apply(Integer ignore) throws Exception {
return getData(configProvider);
}
});
}
});
}
在这里,有一些版本迁移的操作,先不管它,看关键代码getDaga(),这个方法是获取数据的,下面进入源码。
//VisibleForTesting
<T> Observable<T> getData(final io.rx_cache2.ConfigProvider configProvider) {
Record<Object> record = twoLayersCache.retrieve(configProvider.getProviderKey(), configProvider.getDynamicKey(),
configProvider.getDynamicKeyGroup(), useExpiredDataIfLoaderNotAvailable,
configProvider.getLifeTimeMillis(), configProvider.isEncrypted());
Observable<Reply> replyObservable;
if (record != null && !configProvider.evictProvider().evict()) {
replyObservable = Observable.just(new Reply(record.getData(), record.getSource(), configProvider.isEncrypted()));
} else {
replyObservable = getDataFromLoader(configProvider, record);
}
return (Observable<T>) replyObservable.map(new Function<Reply, Object>() {
@Override public Object apply(Reply reply) throws Exception {
return ProcessorProvidersBehaviour.this.getReturnType(configProvider, reply);
}
});
}
这里的关键代码是
if (record != null && !configProvider.evictProvider().evict()) {
replyObservable = Observable.just(new Reply(record.getData(), record.getSource(), configProvider.isEncrypted()));
} else {
replyObservable = getDataFromLoader(configProvider, record);
}
这两句代码的意思是有缓存就从缓存取数据,否在走网络通道。else分支就是走的网络通道
接下来我们继续看取缓存的代码。这里的关键点在record,我们这里看一下record初始化的地方,
Record record = twoLayersCache.retrieve(configProvider.getProviderKey(), configProvider.getDynamicKey(),
从这里我们可以看出record是通过TwoLayersCache这个类初始化的,接下来我们进入这个类,这个类很关键,这里就是它的缓存主要策略实现的地方
@Singleton
public final class TwoLayersCache {
private final EvictRecord evictRecord;
private final io.rx_cache2.internal.cache.RetrieveRecord retrieveRecord;
private final SaveRecord saveRecord;
@Inject public TwoLayersCache(EvictRecord evictRecord, io.rx_cache2.internal.cache.RetrieveRecord retrieveRecord,
SaveRecord saveRecord) {
this.evictRecord = evictRecord;
this.retrieveRecord = retrieveRecord;
this.saveRecord = saveRecord;
}
public <T> Record<T> retrieve(String providerKey, String dynamicKey, String dynamicKeyGroup,
boolean useExpiredDataIfLoaderNotAvailable, Long lifeTime, boolean isEncrypted) {
return retrieveRecord.retrieveRecord(providerKey, dynamicKey, dynamicKeyGroup,
useExpiredDataIfLoaderNotAvailable, lifeTime, isEncrypted);
}
public void save(String providerKey, String dynamicKey, String dynamicKeyGroup, Object data,
Long lifeTime, boolean isExpirable, boolean isEncrypted) {
saveRecord.save(providerKey, dynamicKey, dynamicKeyGroup, data, lifeTime, isExpirable,
isEncrypted);
}
public void evictProviderKey(final String providerKey) {
evictRecord.evictRecordsMatchingProviderKey(providerKey);
}
public void evictDynamicKey(String providerKey, String dynamicKey) {
evictRecord.evictRecordsMatchingDynamicKey(providerKey, dynamicKey);
}
public void evictDynamicKeyGroup(String key, String dynamicKey, String dynamicKeyGroup) {
evictRecord.evictRecordMatchingDynamicKeyGroup(key, dynamicKey, dynamicKeyGroup);
}
public void evictAll() {
evictRecord.evictAll();
}
//Exists for testing purposes
public void mockMemoryDestroyed() {
evictRecord.mockMemoryDestroyed();
}
}
这个类很关键,代码量也不多,所有这里我把它都贴了进来,这个类有三个关键的成员变量
private final EvictRecord evictRecord;
private final io.rx_cache2.internal.cache.RetrieveRecord retrieveRecord;
private final SaveRecord saveRecord;
顾名思义,
evictRecord 驱逐数据,就是删除本地对应缓存
retrieveRecord 获取数据,从本地获取缓存
saveRecord 保存数据,将新数据存入缓存
这个三个类都继承自Action,接下来进入最后一步,看下这个类的源码
private static final String PREFIX_DYNAMIC_KEY = "$d$d$d$";
private static final String PREFIX_DYNAMIC_KEY_GROUP = "$g$g$g$";
protected final Memory memory;
protected final Persistence persistence;
public Action(Memory memory, Persistence persistence) {
this.memory = memory;
this.persistence = persistence;
}
protected String composeKey(String providerKey, String dynamicKey, String dynamicKeyGroup) {
return providerKey
+ PREFIX_DYNAMIC_KEY
+ dynamicKey
+ PREFIX_DYNAMIC_KEY_GROUP
+ dynamicKeyGroup;
}
protected List<String> getKeysOnMemoryMatchingProviderKey(String providerKey) {
List<String> keysMatchingProviderKey = new ArrayList<>();
for (String composedKeyMemory : memory.keySet()) {
final String keyPartProviderMemory =
composedKeyMemory.substring(0, composedKeyMemory.lastIndexOf(PREFIX_DYNAMIC_KEY));
if (providerKey.equals(keyPartProviderMemory)) {
keysMatchingProviderKey.add(composedKeyMemory);
}
}
return keysMatchingProviderKey;
}
protected List<String> getKeysOnMemoryMatchingDynamicKey(String providerKey, String dynamicKey) {
List<String> keysMatchingDynamicKey = new ArrayList<>();
String composedProviderKeyAndDynamicKey = providerKey + PREFIX_DYNAMIC_KEY + dynamicKey;
for (String composedKeyMemory : memory.keySet()) {
final String keyPartProviderAndDynamicKeyMemory =
composedKeyMemory.substring(0, composedKeyMemory.lastIndexOf(PREFIX_DYNAMIC_KEY_GROUP));
if (composedProviderKeyAndDynamicKey.equals(keyPartProviderAndDynamicKeyMemory)) {
keysMatchingDynamicKey.add(composedKeyMemory);
}
}
return keysMatchingDynamicKey;
}
protected String getKeyOnMemoryMatchingDynamicKeyGroup(String providerKey, String dynamicKey,
String dynamicKeyGroup) {
return composeKey(providerKey, dynamicKey, dynamicKeyGroup);
}
这个类有两个关键的成员变量
protected final Memory memory;
protected final Persistence persistence;
顾名思义: memory 内存 这个内就是操作内存的,数据在内存中的删除,查询,保存
persistence 持久层,这个就是磁盘存储, 主要操作数据在磁盘中删除,查询,保存。
它门的关系如下uml图,画的不好看将就看哈
总结一下,TwoLayersCache包括了三种操作,删除,保存,获取缓存的功能。
action提供了,操作磁盘和内存的两种功能。
至此我们就跟完了整体的缓存代码
有兴趣的可以返回ProcessorProvidersBehaviour类的getData方法,跟一下网络加载的分支,和Retrofit类似,
如果有什么疑惑或者错误的地方,请不吝赐教。毕竟真理越辩越明嘛