一些你可能需要的okhttp实现

http://blog.csdn.net/qq_17766199




今天分享一些我在项目中使用到的okhttp实现,由简至难。(以下内容均在okhttp3.4.1下正常使用)


1

okhttp日志打印


这个就简单了,一个工具类。先上代码:


这里我为了打印清晰使用了KLog(https://github.com/ZhaoKaiQiang/KLog)用来打印Log。


使用方法:

OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new LogInterceptor())
                .build();


打印例子: 



当然了,你也可以使用官方提供的Logging Interceptor,也是非常方便。具体参见链接(https://github.com/square/okhttp/blob/master/okhttp-logging-interceptor/README.md)。


2

okhttp网络缓存


(1)首先设置Cache




这里使用getCacheDir()来作为缓存文件的存放路径(/data/data/包名/cache) ,如果你想看到缓存文件可以临时使用 getExternalCacheDir()(/sdcard/Android/data/包名/cache)。


(2)如果我们的服务器支持缓存,那么Response中的头文件中会有Cache-Control: max-age=xxx这样的字段。


如下图:



这里的public意思是可以无条件的缓存该响应,max-age是你缓存的最大存放的时间。比如你设置了6分钟的最大缓存时间,那么6分钟内他会读取缓存,但超过这个时间则缓存失效。具体的响应标头大家可以自行查询。


(3)如果我们的服务器不支持缓存,也就是响应头没有对应字段,那么我们可以使用网络拦截器实现:





设置拦截器:




注意:addInterceptor和addNetworkInterceptor 需要同时设置。 这两者的区别

可以参考Interceptors 拦截器(http://www.jianshu.com/p/2710ed1e6b48)。我只说一下效果,如果你只是想实现在线缓存,那么可以只添加网络拦截器,如果只想实现离线缓存,可以使用只添加应用拦截器。两者都添加,就不用我说了吧。


如果在拦截器中统一配置,则所有的请求都会缓存。


但是在实际开发中有些接口需要保证数据的实时性,那么我们就不能统一配置,这时可以这样:

 @Headers("Cache-Control: public, max-age=时间秒数")
 @GET("weilu/test")
 Observable<Test> getData();

我自己找了一些配置,大家可以根据个人需求使用:


  1. 不需要缓存:Cache-Control: no-cache或Cache-Control: max-age=0

  2. 如果想先显示数据,在请求。(类似于微博等):Cache-Control: only-if-cached


通过以上配置后通过拦截器中的request.cacheControl().toString() 就可以获取到我们配置的Cache-Control头文件,实现对应的缓存策略。


测试一下:


1.首先我设置@Headers("Cache-Control: public,max-age=30")

2.30秒有效期内请求第一次



3.30内请求第二次(在线缓存)




你可能会说没有什么不同,其实仔细看看就会发现,两次的请求响应时间分别为85.5ms和1.5ms,这说明是直接读取的缓存。


同时我们可以查看Monitors中的Network发现并没有请求网络,也同样说明使用的是缓存。


从这里其实也就说明了添加缓存的好处:1.降低了请求的延迟。2.降低网络的频繁请求。


4.30超出后再请求一次结果与第二步一致。



缓存失效,重新请求。


5.关闭网络后超过30s请求一次(离线缓存)



这时发现警告响应失效。这说明已经超过30秒,如果没有超出则没有警告。大家可以自行尝试。


最后感兴趣的可以去我们设置的缓存目录查看一下缓存文件,你一定会有新的发现。


3

okhttp实现token过期刷新


(1)使用拦截器实现,这个具体参看这篇文章(http://www.jianshu.com/p/62ab11ddacc8),我自己没有试过,提供出来给大家拓展一下思路。

(2)使用RxJava的操作符retryWhen 实现。这个是我在项目中使用的方法,也是重点说明的方法。


首先说明一下我们这边的情况,我们的登录验证使用的是登陆成功后包含在响应头文件中的Set-Cookie,这其中有sessionId,凡是需要登录操作的只需请求

时带上他即可。


登录超时时服务器会返回code为401的json来告知我们登录超时。那么其实就很简单了,只需要判断code是否为401,是则登录一下保存新的Cookie,在重新请求一下之前的操作就行了。


下来我来实现以下,至于其他的情况其实大同小异。


首先我们来说明一下retryWhen,retryWhen操作符是在源Observable出现错误或者异常时,通过回调另一个Observable来判断是否重新尝试执行源Observable的逻辑,如果这个Observable没有错误或者异常出现,则就会重新尝试执行源Observable的逻辑,否则就会直接回调执行订阅者的onError方法。

看了上面的概念是不是有点绕,其实意思就和他的名字一样“重试”,而触发的条件是有了“错误”,错误解决,那么再试一次。其实这就和我们需要解决的问题一样,登录失败(触发)–> 重新登录(解决) –> 重试。


首先定义一个父类。

 public class TimeOut {
    private int timeout;
    public int getTimeout() {
        return timeout;
    }
    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }
}

自定义一个异常,可以不用实现

public class TimeOutException extends Exception{
}

简单封装了一下,这样不用重复书写超时判断。




TimeOutRetry 类:




使用:




注意这里的Test类需要继承TimeOut。


结果如图:



看完这么多,我们可以看到这些功能都可以利用拦截器去实现,可见它的强大之处。(补充:说到了拦截器,突然想到了Facebook出的一个强大的Android调试工具stetho(https://github.com/facebook/stetho),该工具让你可以在谷歌浏览器查看App的布局,preference,网络请求,数据库,一切都是可视化的操作,不需要root你的设备。


其中也支持okhttp,使用方法就是添加一个网络拦截器。)还有一些实现,比如https的访问,cookie的同步问题我就不一一去说了,我们可以参考okhttputils(https://github.com/hongyangAndroid/okhttputils)与okhttp-OkGo (https://github.com/jeasonlzy/okhttp-OkGo)去实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值