Retrofit2.0+okhttp3实现缓存

作者: TiaoPi | 来源:发表于2016-07-13 20:21 被阅读2204次

    参考文章:Retrofit2.0+okhttp3缓存机制以及遇到的问题

    参考文章 : 使用Retrofit和Okhttp实现网络缓存。无网读缓存,有网根据过期时间重新请求

    参考文章 : okhttp3 retrofit2 缓存问题

    我是按照上面文章的思路,把缓存加入到自己的项目

    • 首先就是思路和基本基本一样的

    然后就是我自己在弄的时候发现一些问题

    Fatal Exception thrown on Scheduler.Worker thread

    出现这个问题的主要原因就是Retrofit 和OKHttp 的版本问题
    我自己用到的 Retrofit2的版本是2.1.0版本,也就是最新的, OKHttp 3的版本是3.4.0 但是这样的组合就是出现了问题,

    java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
           at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:54)
           at android.os.Handler.handleCallback(Handler.java:739)
           at android.os.Handler.dispatchMessage(Handler.java:95)
           at android.os.Looper.loop(Looper.java:145)
           at android.app.ActivityThread.main(ActivityThread.java:5938)
           at java.lang.reflect.Method.invoke(Method.java)
           at java.lang.reflect.Method.invoke(Method.java:372)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1389)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1184)
    

    在网上也看了好多解决办法,这类的问题发现的也不多,网上的办法也不好使,然后就想到了版本问题

    我目前有就两种的解决方案,第一种就是更改对应的版本

    我现在使用的版本目前是没有问题的

        //compile 'com.squareup.okhttp3:okhttp:3.4.1'
        compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'
        compile 'com.squareup.retrofit2:adapter-rxjava:2.0.1'
        compile 'com.squareup.retrofit2:converter-gson:2.0.1'
        //TODO换这个版本就没问题  否则会出现 线程调度异常
        compile 'com.squareup.okhttp3:okhttp:3.0.1'
    

    然后还有一种解决方案,昨天一不小心就可以了,但是写Okhttp缓存的时候有一次出现了类似的问题,我先贴出来(我觉得还是版本的问题更大一些)

    
    o.subscribeOn(Schedulers.io())
                    .unsubscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(subscriber);
    

    就是这样

    • 然后就是我自己的代码,主要还是参考网络上很多很多文章

    缓存的主要目的还是在没有网络的情况不至于一片白花花的view,然后就是不用每次都请求下载数据

    我们还是用OkHttp缓存

    上面文章都很明白我直接上代码就OK
    首先就是需要添加addInterceptor和 addNetworkInterceptor这两个
    这两个现在要必须都设置才能缓存否则的话不行,其他依赖版本的我也没有试

    先说添加的Interceptor
    这个主要是设置有网就去网络,没网就读取本地的缓存

     /**
         * 设置返回数据的  Interceptor  判断网络   没网读取缓存
         */
        public Interceptor getInterceptor(){
            return new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    if (!APPNetWork.isNetworkConnected(App.getIntense())) {
                        request = request.newBuilder()
                                .cacheControl(CacheControl.FORCE_CACHE)
                                .build();
                    }
                    return chain.proceed(request);
                }
            };
        }
    

    另外一个就是NetWorkInterceptor

     /**
         * 设置连接器  设置缓存
         */
        public Interceptor getNetWorkInterceptor (){
            return new Interceptor() {
                @Override
                public Response intercept(Chain chain) throws IOException {
                    Request request = chain.request();
                    Response response = chain.proceed(request);
                    if (APPNetWork.isNetworkConnected(App.getIntense())) {
                        int maxAge = 0 * 60;
                        // 有网络时 设置缓存超时时间0个小时
                        response.newBuilder()
                                .header("Cache-Control", "public, max-age=" + maxAge)
                                .removeHeader("Pragma")
                                .build();
                    } else {
                        // 无网络时,设置超时为1周
                        int maxStale = 60 * 60 * 24 * 7;
                        response.newBuilder()
                                .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                                .removeHeader("Pragma")
                                .build();
                    }
                    return response;
                }
            };
        }
    

    最后看一下client设置进去就行了

                    .addNetworkInterceptor(getNetWorkInterceptor())
                    .addInterceptor(getInterceptor())
    
    输入图片说明输入图片说明

    这个就是缓存文件

    相关文章

      网友评论

      • 飞天舞乐:谢谢楼主分享,缓存这块我做了封装,使用起来更方便一些,欢迎大家拍砖讨论:
        https://github.com/yale8848/RetrofitCache
        __362d:大神,你GitHub封装的这个,有没有使用的博客参照一下呀。或者使用的demo!能加个qq嘛??727888035
      • 63d7328b70bf:楼主啊,我按你的代码写,遇到HTTP 504 Unsatisfiable Request (only-if-cached)问题了
        请问你知不知道怎么解决啊?
        谢谢!!
        Hancock1993:@b2c65f6b21dd 是不是没设置cache啊?
        b2c65f6b21dd:POST不能缓存
      • yunhen:我最近正在学习retrofit,我也遇到线程调度异常,不过是因为我没加网络权限

      本文标题:Retrofit2.0+okhttp3实现缓存

      本文链接:https://www.haomeiwen.com/subject/aiqejttx.html