RxCache——Retrofit缓存库

RxCache——Retrofit缓存库

Retrofit是当下最火的网络请求库,其同门师兄网络请求库okhttp自带缓存,但是okhttp的缓存必须配合Header使用,比较麻烦,也不够灵活;对于Retrofit,RxCache是一款为其量身定制的缓存库
RxCache使用注解来为Retrofit配置缓存信息,内部使用动态代理和Dagger来实现。Github官方教程:RxCache官方文档,官方文档是全英的,受不了的同学可以参考“却把清梅嗅”博主翻译的中文文档(个人英语渣实在无能为力,还是大神强大):RxCache官方中文文档
JessYan大神的简书:你不知道的Retrofit缓存库RxCache,其中有RxCache的架构图,有兴趣的可以研究。
一、使用

  1. 定义接口
    和Retrofit类似,接口中的每个方法和Retrofit接口中的方法一一对应,每个方法参数必须传入对应Retrofit接口方法的返回值(返回值必须为Observable,否则报错)。参数DynamicKey、DynamicKeyGroup和EvictProvider是可选的。
    在这里插入图片描述
  2. 将接口实例化
    和Retrofit构建方法类似,将接口通过using方法传入,返回一个接口的动态代理对象,调用该对象的方法传入对应参数就可以实现缓存了,通过注解和传入不同的参数可以实现自定义的参数
    在这里插入图片描述
    与Retrofit结合使用的例子如下:
    在这里插入图片描述

二、参数详解
在这里插入图片描述
1 . 参数Observable
参数Observable的意义为将想缓存的Retrofit接口作为参数传入,RxCache会在没有缓存、缓存过期或者EvictProvider为true****时,通过这个Retrofit接口重新请求最新的数据,并且将服务器返回的结果包装成Repley返回,返回之前会向内存缓存和磁盘缓存各保存一份
在这里插入图片描述
如果需要知道返回结果是来自哪里(本地、内存还是网络)以及是否加密,则可以使用Observable<Reply<List>>作为方法的返回值,这样RxCache则会使用Reply包装结果,如果没有这个需求则直接在泛型中声明结果的数据类型为Observable<List>
例外:如果构建RxCache的时候将useExpireDateIfLoaderNoAvaiable设置成true,会在数据为空或发生错误时,忽略EvictProvider为true或缓存过期的情况,继续使用缓存(前提是之前请求过,有缓存)。
2 . DynamicKey & DynamicKeyGroup
需要提一下,RxCache并不是通过使用URL充当标识符来存储和获取缓存的,而是通过DynamicKey和DymaicKeyGroup对象加上CacheProviders接口中声明的方法名,组合成一个标识符,通过这个标识符来存储和获取缓存。
在这里插入图片描述
在这里插入图片描述
举个例子来了解一下这个两个参数到底有什么用途:
在这里插入图片描述
有一个接口具有分页功能,使用RxCache给他设置了3分钟的缓存,如果这两个对象都不传入参数中,它会默认使用这个接口的方法名去存储和获取缓存,也就是说使用这个接口获取到了第一页的数据,三分钟以内多次调用这个接口,请求其他分页的数据,它返回的依旧是第一页的缓存数据,直到缓存过期。
DynamicKey内部存储有一个Key,在构建的时候传入页数,RxCache将会根据不同的页数分别保存一份缓存,它内部做的事就是将方法名+DynamicKey变成一个String类型的标识符去获取和存储缓存。
DynamicKey和DynamicKeyGroup的关系:
DynamicKey存储有一个Key,应用场景为:请求同一个接口,需要参照一个变量的不同返回不同的数据,比如分页,构造时传入页数即可。
DynamicKeyGroup存储有两个Key,是在DynamicKey的基础上的加强,应用场景:请求同一个接口不仅需要分页,还需要用户标识符,那么可以构造DynamicKeyGroup时,第一个参数传页数,第二个参数传用户标识符即可。
在这里插入图片描述
理论上DynamicKey和DynamicKeyGroup根据不同的需求只用一个即可,但是也可以两个参数都传入,以上面需求为例子,两个参数都传入的话,会先取DynamicKey的Key(页数)然后再取DynamicKeyGroup的第二个Key(用户标识符),加上接口名组成标识符来获取和存储缓存,这样就忽略了DynamicKeyGroup的第一个Key(页数)。
3 .EvictProvider & EvictDynamicKey & EvictDynamicKeyGroup
这三个对象是互相继承关系,继承关系为EvictProvider > EvictDynamicKey > EvictDynamicKeyGroup,这三个对象只能传其中一个,多传一个都会报错。(通俗的讲,EvictProvie是EvictDynamicKey的粑粑,EviDynamicKey是EvitDynamicKeyGroup的粑粑)。
在这里插入图片描述
那么这三者的不同之处在哪里?
在这里插入图片描述
如果有未过期的缓存,并且里面的boolean为false****时,这三者都一样直接使用缓存并且不会删除缓存;而boolean为true时就有区别,RxCache会在Retrofit请求到新数据后,在boolean为true删除对应的缓存,最主要的区别在于删除的规则
三者在boolean为true的时候的删除规则(以一个接口为例,该接口会根据不同分页返回不同的数据,并且一个分页还要根据不同用户显示不同数据):
三个都不传,RxCache自动new EvictProvider(false),即默认情况下为false,不会删除任何缓存
② EvictDynamicKeyGroup只会删除对应分页下,对应用户的缓存
③ EvictDynamicKey会删除对应分页下的所有缓存
④ EvictProvide会删除当前接口下的所有缓存
如果请求的这个接口没有分页功能,并且不需要使用缓存,那么应该传EvictProvide并且构造的时传入true,但是传入其他两对象达到的效果也是一样的。

三、注解

  1. @LifeCache
    @LifeCache用来定义缓存的生命周期,当Retrofit获取到最新的数据时,会将数据以及数据的配置信息封装成Record,在本地和内存各保存一份,Record中则保存了@LifeCache的值(毫秒)和当前数据请求成功的时间(毫秒)。
    以后每次取缓存时,会判断缓存的保存时候是否过期,过期则立即清理缓存,并使用Retrofit重新请求新的数据,如果EvictProvide为true,不管缓存是否过期都会重新请求数据。
  2. @EncryptKey & @Encrypt
    用于给缓存加密,区别在于作用域不同。@EncryptKey是作用在接口上,而@Encrypt是作用在方法上。
    在这里插入图片描述
    如果需要给某个请求接口的缓存做加密操作,则在对应方法上加上@Encrypt,在存储和获取缓存时,RxCache会使用@EncryptKey的值作为Key给缓存数据进行加解密,因此每个Providers中的所有方法都只能使用相同的key进行加解密。
    在这里插入图片描述
    注意:RxCache只会给本地缓存进行加密操作,并不会给内存缓存进行加密。
  3. @Expirable
    之前说过每次Retrofit重新获取新的数据时,会在本地缓存和内存缓存各保存一份,存储完毕后,会检查现在的本地缓存大小,如果现在本地缓存中存储的所有缓存大小大于或者等于setMaxMBPersistenceCache(构建RxCache可以设置缓存大小)中设置的大小(默认为100MB)的95%,RxCache则会进行删除操作
    RxCache会遍历构建RxCache时传入的cacheDirectory中的所有缓存数据,一个个删除直到总大小小于70%,遍历的顺序不能保证
    在这里插入图片描述
    这个时候@Expirable就派上用场了,在方法上使用并且设置为false(没有使用注解,默认为true),就可以保证这个接口的缓存数据,在每次需要清理的时候能幸免于难。
    在这里插入图片描述
    PS:构造RxCache时persitence方法传入的cacheDirectory是用来存放本地缓存的文件夹,最好不要存放除此之外的任何数据,避免每次遍历清理缓存的时产生不必要的开销。
  4. @SchemeMigration & @Migration
    在这里插入图片描述
    首先了解一下数据迁移:在最新的版本中某个接口返回值类型内部发生了改变,从而获取数据的方式发生了改变,但是存储在本地的数据是未改变的版本,这样在反序列化时就可能发生错误。
    在这里插入图片描述
    数据迁移解决上述问题的方法:使用注解声明,之前有缓存并且内部修改过的class,RxCache会把含有这些class的缓存全部清除掉
    在这里插入图片描述
    值得一提的是,在每次创建接口的动态代理时,也就是在每次调用RxCache.using时,会执行两个清理,清理含有@Migration中声明的evictClasses的缓存,以及遍历本地缓存文件夹清理所有已经过期的缓存
    每次清理完需要数据迁移的缓存时,会将version值最大的@Maigration的version值保存到本地。
    在这里插入图片描述
    它会将3保存到本地,每次调用using()开始数据迁移时会将上次保存的version值从本地取出来,查找@SchemeMigration中大于这个version值的@Migration,取出里面evictClasses,去重后,遍历所有本地缓存,只要缓存数据中含有声明的class,就将这个缓存清除。

资料参考:JessYan:你不知道的Retrofit缓存库RxCache
Github官网:RxCache官方文档
RxCache官方文档中文翻译

展开阅读全文

没有更多推荐了,返回首页