http://blog.csdn.net/windboy2014/article/details/52711188
1.认真的查看其源码之后,我们可以修改源码达到缓存功能;
RxCache的构建方式和Retrofit类似使用Builder构建
providers = new RxCache.Builder()
.persistence(cacheDir, new GsonSpeaker())
.using(Providers.class);
调用using,而using中使用的动态代理所有方法都会走InvocationHandler的invoke方法
public T using(final Class<T> classProviders) {
proxyProviders = new ProxyProviders(builder, classProviders);
return (T) Proxy.newProxyInstance(
classProviders.getClassLoader(),
new Class>[] {classProviders},
proxyProviders);
}
相应的ProxyProviders的代理提供类在RxCache 1.5.2版本中使用的dagger2方式创建,ProxyProviders实现了InvocationHandler,所有的方法都会走invoke方法
@Override public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable {
return Observable.defer(new Func0>() {
@Override public Observable
先看看ProxyTranslator的processMethod方法
ConfigProvider processMethod(Method method, Object[] objectsMethod) {
ConfigProvider prev = loadConfigProviderMethod(method);
ConfigProvider configProvider = new ConfigProvider(prev.getProviderKey(),
null, prev.getLifeTimeMillis(), prev.requiredDetailedResponse(), prev.isExpirable(),
prev.isEncrypted(), getDynamicKey(method, objectsMethod),
getDynamicKeyGroup(method, objectsMethod),
getLoaderObservable(method, objectsMethod),
evictProvider(method, objectsMethod));
return configProvider;
}
传入方法和相应的参数,使用ConfigProvider 进行包装起来,并返回一个包装类ConfigProvider ,再回过头来看ProcessorProviders的process方法,点开一看是个接口,而对应的实现类是有dagger2生成的。查看RxCacheModule(管理RxCache中的注解注入参数的类)的provideProcessorProviders方法
@Provides ProcessorProviders provideProcessorProviders(
ProcessorProvidersBehaviour processorProvidersBehaviour) {
return processorProvidersBehaviour;
}
相应的实现类是ProcessorProvidersBehaviour 的process方法
@Override
public Observable process(final ConfigProvider configProvider) {
return (Observable) Observable.defer(new Func0>() {
@Override public Observable
Record记录的是缓存数据,缓存逻辑基本就在这个类里面TwoLayersCache的retrieve方法中
public Record retrieve(String providerKey, String dynamicKey, String dynamicKeyGroup,
boolean useExpiredDataIfLoaderNotAvailable, Long lifeTime, boolean isEncrypted) {
return retrieveRecord.retrieveRecord(providerKey, dynamicKey, dynamicKeyGroup,
useExpiredDataIfLoaderNotAvailable, lifeTime, isEncrypted);
}
其调用RetrieveRecord的retrieveRecord方法
Record retrieveRecord(String providerKey, String dynamicKey, String dynamicKeyGroup,
boolean useExpiredDataIfLoaderNotAvailable, Long lifeTime, boolean isEncrypted) {
String composedKey = composeKey(providerKey, dynamicKey, dynamicKeyGroup);
//内存中读取数据
Record record = memory.getIfPresent(composedKey);
if (record != null) {
//存在标记为内存数据
record.setSource(Source.MEMORY);
} else {
try {
//SD卡中寻找,标记为sd卡数据
record = persistence.retrieveRecord(composedKey, isEncrypted, encryptKey);
record.setSource(Source.PERSISTENCE);
memory.put(composedKey, record);
} catch (Exception ignore) {
return null;
}
}
//记录生命周期
record.setLifeTime(lifeTime);
//判断是否超过保存的时间
if (hasRecordExpired.hasRecordExpired(record)) {
//根据规则是否清除缓存
if (!dynamicKeyGroup.isEmpty()) {
evictRecord.evictRecordMatchingDynamicKeyGroup(providerKey, dynamicKey,
dynamicKeyGroup);
} else if (!dynamicKey.isEmpty()) {
evictRecord.evictRecordsMatchingDynamicKey(providerKey, dynamicKey);
} else {
evictRecord.evictRecordsMatchingProviderKey(providerKey);
}
return useExpiredDataIfLoaderNotAvailable ? record : null;
}
return record;
}
源码解读依据这个解读的
//VisibleForTesting
Observable getData(final ConfigProvider configProvider) {
return (Observable) Observable.just(
twoLayersCache.retrieve(configProvider.getProviderKey(), configProvider.getDynamicKey(),
configProvider.getDynamicKeyGroup(), useExpiredDataIfLoaderNotAvailable,
configProvider.getLifeTimeMillis(), configProvider.isEncrypted()))
.map(new Func1>() {
@Override public Observable call(final Record record) {
//evict() true no cache ,false cache data
if (record != null && !configProvider.evictProvider().evict()) {
//从网络获取数据
return getDataFromClond(configProvider, record);
}
//从网络获取数据如果失败,使用缓存数据
return getDataFromLoader(configProvider, record);
}
}).flatMap(new Func1, Observable>() {
@Override
public Observable call(Observable responseObservable) {
return responseObservable.map(new Func1() {
@Override
public Object call(Reply reply) {
return getReturnType(configProvider, reply);
}
});
}
});
}
private Observable getDataFromLoader(final ConfigProvider configProvider,
final Record record) {
return configProvider.getLoaderObservable().map(new Func1() {
@Override public Reply call(Object data) {
//has Data
boolean useExpiredData = configProvider.useExpiredDataIfNotLoaderAvailable() != null ?
configProvider.useExpiredDataIfNotLoaderAvailable()
: useExpiredDataIfLoaderNotAvailable;
if (data == null && useExpiredData && record != null) {
return new Reply(record.getData(), record.getSource(), configProvider.isEncrypted());
}
clearKeyIfNeeded(configProvider);
if (data == null) {
throw new RxCacheException(Locale.NOT_DATA_RETURN_WHEN_CALLING_OBSERVABLE_LOADER
+ " "
+ configProvider.getProviderKey());
}
//保存缓存数据
twoLayersCache.save(configProvider.getProviderKey(), configProvider.getDynamicKey(),
configProvider.getDynamicKeyGroup(), data, configProvider.getLifeTimeMillis(),
configProvider.isExpirable(), configProvider.isEncrypted());
return new Reply(data, Source.CLOUD, configProvider.isEncrypted());
}
}).onErrorReturn(new Func1() {
@Override public Object call(Object o) {
boolean useExpiredData = configProvider.useExpiredDataIfNotLoaderAvailable() != null ?
configProvider.useExpiredDataIfNotLoaderAvailable()
: useExpiredDataIfLoaderNotAvailable;
if (record != null) {
//请求失败,并且缓存数据存在,使用缓存数据
return new Reply(record.getData(), record.getSource(), configProvider.isEncrypted());
}
throw new RxCacheException(Locale.NOT_DATA_RETURN_WHEN_CALLING_OBSERVABLE_LOADER
+ " "
+ configProvider.getProviderKey(), (Throwable) o);
}
});
}
private Observable getDataFromClond(final ConfigProvider configProvider,
final Record record) {
return configProvider.getLoaderObservable().map(new Func1() {
@Override public Reply call(Object data) {
clearKeyIfNeeded(configProvider);
if (data == null) {
throw new RxCacheException(Locale.NOT_DATA_RETURN_WHEN_CALLING_OBSERVABLE_LOADER
+ " "
+ configProvider.getProviderKey());
}
//仅仅使用网络数据
return new Reply(data, Source.CLOUD, configProvider.isEncrypted());
}
}).onErrorReturn(new Func1() {
@Override public Object call(Object o) {
throw new RxCacheException(Locale.NOT_DATA_RETURN_WHEN_CALLING_OBSERVABLE_LOADER
+ " "
+ configProvider.getProviderKey(), (Throwable) o);
}
});
}
使用方式会变一下
/**
*
* @param update 是否更新,如果设置为true,向服务器请求数据,如果成功使用新数据,失败使用缓存数据
* @return
*/
public Observable>> getUsers(int idLastUserQueried, final boolean update) {
//这里设置idLastUserQueried为DynamicKey,
return cacheProviders.getUsers(restApi.getUsers(idLastUserQueried, USERS_PER_PAGE), new DynamicKey(idLastUserQueried), new EvictDynamicKey(update));
}
例子源码li-MVPArms
给个start