RxCache的使用,RxCache与Retrofit2.0结合使用

最近学习了Retrofit2.0,接下来自然少不了Rxcache的学习,

RxCache是一个好用的缓存类库,可以直接和Retrofit结合使用

但是,我从上周六开始浏览网上的介绍,大部分都是直接从官方介绍那里直接翻译一遍就草草了事,没有什么具体的实现步骤

最后无奈只好下载了官方的Demo来看 Demo链接 点击打开链接,注意此学习此Demo,直接用AS打开RxCacheSamples根目录就可以了,不要选择根目录下的sample_android进行打开。

下边我跟据网上的资料和学习Demo自己写了一个Retrofit和rxcache结合使用的小练习:

retrofit可以看我上一篇的介绍:点击打开链接

一,添加依赖

 
 
compile "com.github.VictorAlbertos.RxCache:runtime:1.8.3-2.x"
compile "io.reactivex.rxjava2:rxjava:2.1.6"

compile 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
//Caused by: java.lang.IllegalArgumentException: Could not locate call adapter for rx.Observable<>

compile 'com.squareup.retrofit2:retrofit:2.4.0'
compile 'com.squareup.retrofit2:converter-gson:2.4.0'

compile 'com.github.VictorAlbertos.Jolyglot:gson:0.0.3'
compile 'io.reactivex.rxjava2:rxandroid:2.0.0'

repositories {
    google()
    jcenter()
    maven { url "https://jitpack.io" }
}


二:看下这个小Demo的结构:



可以按照以下的顺序创建类,更有助于消化吸收

News               :     和Retrofit 中存放的数据类一样  就是一个Bena类

RestApi            :      Retrofit的接口类

CacheProvider :    用来创建一个RxCaChe的接口

Repository       :    Retrofit和RxCaChe的具体结合操作,以及是一个接口类

MainActivity    :    执行网络请求操作


三:具体代码实现:

  1. 这个Demo我还是使用了和风天气的Api接口来实现,所以还是和在我上篇Retrofit中一样直接用GsonFormat创建一个News类,简单方便又实用,如下:
    private List<HeWeather6Bean> HeWeather6;
    
    public List<HeWeather6Bean> getHeWeather6() {
        return HeWeather6;
    }
    
    public void setHeWeather6(List<HeWeather6Bean> HeWeather6) {
        this.HeWeather6 = HeWeather6;
    }
    
    public static class HeWeather6Bean {
        /**
         * basic : {"cid":"CN101010100","location":"北京","parent_city":"北京","admin_area":"北京","cnty":"中国","lat":"39.90498734","lon":"116.4052887","tz":"+8.00"}
         * update : {"loc":"2018-05-08 15:47","utc":"2018-05-08 07:47"}
         * status : ok
         * now : {"cloud":"0","cond_code":"100","cond_txt":"晴","fl":"23","hum":"24","pcpn":"0.0","pres":"1016","tmp":"25","vis":"10","wind_deg":"265","wind_dir":"西风","wind_sc":"2","wind_spd":"8"}
         */
    
        private BasicBean basic;
        private UpdateBean update;
        private String status;
        private NowBean now;
    
        public BasicBean getBasic() {
            return basic;
        }
    
        public void setBasic(BasicBean basic) {
            this.basic = basic;
        }
    
        public UpdateBean getUpdate() {
            return update;
        }
    
        public void setUpdate(UpdateBean update) {
            this.update = update;
        }
    
        public String getStatus() {
            return status;
        }
    
        public void setStatus(String status) {
            this.status = status;
        }
    
        public NowBean getNow() {
            return now;
        }
    
        public void setNow(NowBean now) {
            this.now = now;
        }
    

News类的代码就不贴全了,

2:RestApi类:   跟普通的Retrofit接口没有什么区别

public interface RestApi {


    @POST("s6/weather/now?parameters")
    Observable<News> getUsers(@Query("key")String key, @Query("location")String location);

}

3:CacheProvider类:

public interface CacheProvider {

    @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES)//
    Observable<Reply<News>> getRepos(Observable<News> ouser);
}

请注意:1: @LifeCache设置缓存过期时间. 如果没有设置@LifeCache, 数据将被永久缓存

                       除非你使用了其他的清除缓存的标注,这个一会我们再说。

              2: 此接口写的里面的第一个参数要写成你Retrofit接口中开头的一段,可以从上边的代码和下边的代码仔细看一下

                    当然,这里我们只设置了一个参数,也就是必需的参数

                    如果只设置这个所必需的参数和没有设置@LifeCache那么只要本地缓存没有消失,就会每次都进行本地读取数                          据。其他参数是一些 清除缓存的标注,我们先进行一次简单的数据请求与缓存,再写关于其他标注的事情。 一会                        再说。

4:Repository 类

//调用此处,用来生成一个缓存文件
public static Repository init(File cacheDir) {
    return new Repository(cacheDir);
}

private final CacheProvider cacheProvider;
private final RestApi restApi;

public Repository(File cacheDir) {

    cacheProvider = new RxCache.Builder()
            .persistence(cacheDir, new GsonSpeaker())
            .using(CacheProvider.class);


    restApi = new Retrofit.Builder()
            .baseUrl("https://free-api.heweather.com/")
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
            .create(RestApi.class);

}


//真正进行数据请求和缓存的接口
public Observable<Reply<News>> getRepos(String key, String location) {
    return cacheProvider.getRepos(restApi.getUsers(key, location));
}

5:MainActivity  进行网络请求和缓存操作

private Repository repository;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    repository = Repository.init(getFilesDir());
    initData();
}

private void initData() {

    repository.getRepos("fad6d6b2cda14ef69d260ea9a4415e31", "北京")
            .subscribeOn(Schedulers.newThread())
            .subscribe(new Consumer<Reply<News>>() {
                @Override
                public void accept(Reply<News> newsReply) throws Exception {
                    News.HeWeather6Bean bean = newsReply.getData().getHeWeather6().get(0);
                    Log.e("TagSuccess", bean.getNow().getCond_txt());
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Log.e("TagErr", throwable.getMessage());
                }
            });

}

现在看下控制台Log 还有看一下我们的网络请求流量

E/TagSuccess: 晴


ok 然后我们马上在两分钟之内再次运行一下程序

再看一下Log 和流量状态:

E/TagSuccess: 晴



我们在第二次在两分钟之内运行程序的时候发现并没数据变动,可是控制台还是打印出了Log,说明我们第一次使用Retrofit结合RxCache进行网络请求和缓存成功了!,  

至于为什么在两分钟之内,是因为我们在CacheProvider类中设置了@lifeCache是两分钟,你也可以等到两分钟或者改变一下@lifecache的时间在进行一次测试,看一下会不会有流量变化。


四 :ok 完成了上边的请求,我觉得应该对具体的代码流程有了清晰地理解
       接下来看一下我们之前所说的 清除缓存的标注

  • EvictProvider                               可以明确地清理清理所有缓存数据.
  • EvictDynamicKey                        可以明确地清理指定的数据, 
  • EvictDynamicKeyGroup              允许明确地清理一组特定的数据. 
  • DynamicKey                                驱逐与一个特定的键使用EvictDynamicKey相关的数据。比如分页,排序或筛选要求

  • DynamicKeyGroup。                  驱逐一组与key关联的数据,使用EvictDynamicKeyGroup。比如分页,排序或筛选要求

这些标注实际上就是用来写在Cacheprovider接口中的一些参数

代码如下修改   修改或者添加的代码我都用红的标注了,一目了然。

CaCheProvider:

public interface CacheProvider {

    @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES)
    Observable<Reply<News>> getRepos(Observable<News> ouser, EvictProvider evictProvider);
}
Respository:

//真正进行数据请求和缓存的接口
public Observable<Reply<News>> getRepos(String key, String location,final boolean updata) {
    return cacheProvider.getRepos(restApi.getUsers(key, location),new EvictProvider(updata));
}

MainActivity:

private boolean upData;
upData=false;
repository.getRepos("fad6d6b2cda14ef69d260ea9a4415e31", "北京",upData)
        .subscribeOn(Schedulers.newThread())

这边upData 设置成true的话就表示清除所有缓存了 ,可以看一下 你的控制台是不是每次打开都是有数据请求,


设置成false的话就是不删除缓存,就是跟不设置EvictProvider    一个样子了!


五:EvictDynamicKey        和DynamicKey     
     清除指定的字段

1:添加CacheProvider的接口         restApi的话就不用改了,还是用之前和风天气的接口 

public interface CacheProvider {

    @LifeCache(duration = 2, timeUnit = TimeUnit.MINUTES)
    Observable<Reply<News>> getRepos(Observable<News> ouser, EvictProvider evictProvider);

    Observable<Reply<News>> getTwo(Observable<News> ouser,DynamicKey dynamicKey,EvictDynamicKey evictDynamicKey);
}

2:Repository类

//真正进行数据请求和缓存的接口
public Observable<Reply<News>> getRepos(String key, String location,final  boolean updata) {
    return cacheProvider.getRepos(restApi.getUsers(key, location),new EvictProvider(updata));
}
public Observable<Reply<News>>getTwo(String key,String location, String data,final  boolean updata){
    return cacheProvider.getTwo(restApi.getUsers(key,location),new DynamicKey(data),new EvictDynamicKey(updata));
}

3:MainActivity


直接添加一个方法来调用 Repository类中新建的getTwo

private void two() {
    upData=true;
    repository.getTwo("fad6d6b2cda14ef69d260ea9a4415e31","济南", bean.getStatus(),upData)
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Consumer<Reply<News>>() {
                @Override
                public void accept(Reply<News> newsReply) throws Exception {
                    Log.e("TwoTagSuccess", bean.getStatus() + "");
                }
            }, new Consumer<Throwable>() {
                @Override
                public void accept(Throwable throwable) throws Exception {
                    Log.e("aaaaaaaa",throwable.toString());
                }
            });

}

之前的initdata()方法先执行进行获取数据,然后在执行这个 two方法用来删除getStatus()字段中的内容

可以对比一下 updata 是true 和flase 的流量情况是不是如下:

updata=true:删除这个字段的数据再次请求,可以看到 有两次流量请求


updata=flase:不删除,只有一次 流量请求


RxCache和ReFrofit结合使用就是如上了,

欢迎各位看到的小伙伴能够给出意见和建议。

猜你喜欢

转载自blog.csdn.net/weixin_40350174/article/details/80257107