系列文章:
1-准备工作
2-搭建项目框架
3-功能实现
4-加入网络缓存
经过前面的几项工作, 项目框架和功能开发规范已经差不过出来了. 接下来要做的就说迭代功能, 和完善细节了.
今天我们要做的是给我们的网络请求加入缓存机制. 类似于一般的阅读类App, 缓存机制一般如下:
缓存之所以必要, 最重要的是能给用户以良好的体验.
另外网络数据缓存也是App网络流量优化, 电量优化的一个必要手段.
要做到缓存仅需要三步:
private static final long CACHE_SIZE = 1024 * 1024 * 50; @Override public OkHttpClient.Builder customize(OkHttpClient.Builder builder) { // set cache dir File cacheFile = new File(mContext.getCacheDir(), "github_repo"); Cache cache = new Cache(cacheFile, CACHE_SIZE); builder.cache(cache); ... return builder; }
顾名思义, "Cache-Control"请求头就是用来控制缓存的. 它有一些属性值来指定缓存的属性, 诸如公共属性, 是否可缓存以及缓存的有效期等.
关于"Cache-Control"的详细解释和使用请自行google...在此略过.
个人也有计划写一些关于HTTP协议相关的基础知识, 会聊到Cache-Control, 敬请期待.
以获取Github Trending这个接口为例:
@Headers("Cache-Control: public, max-age=180") @GET("trending?languages[]=java&languages[]=swift&languages[]=objective-c&languages[]=bash&languages[]=python&languages[]=html") Observable<TrendingResultResp> getTrendingRepos();
众所周知, Response是由服务器控制的, 我们如何加入"Cache-Control"头呢? 方法有二:
大多数情况下, 服务器可能并不受我们控制. 服务器开发人员开发多个系统, 对端的缓存需求不熟悉, 又或是服务器接口并不是我们自己开发的, 例如本系列做的这个 GithubApp .
所幸, OkHttp提供了interceptor来让我们对request, response进行拦截处理, 加入我们想要的请求头等.
如下是本例使用的Cache Interceptor:
private final Interceptor mCacheControlInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (!NetworkUtil.isNetworkAvailable(mContext)) { request = request.newBuilder() .cacheControl(CacheControl.FORCE_CACHE) .build(); } Response originalResponse = chain.proceed(request); if (NetworkUtil.isNetworkAvailable(mContext)) { String cacheControl = request.cacheControl().toString(); return originalResponse.newBuilder() .header("Cache-Control", cacheControl) .build(); } else { return originalResponse.newBuilder() .header("Cache-Control", CacheControl.FORCE_CACHE.toString()) .build(); } } };
如下拦截器, 做了:
做好了拦截器, 不要忘记加到OkHttpClient中:
builder.addNetworkInterceptor(mCacheControlInterceptor);
严重注意, 在加入interceptor时:
使用的是addNetworkInterceptor, 而非addInterceptor.
二者区别参见 OkHttp wiki的Interceptor介绍 , 在此就借个图来用下:
正所谓一图千字, 可以很清楚的看到CACHE的层次了...具体的分析大家还是 Read the fucking source code 吧:)
这里就说明下为什么要使用addNetworkInterceptor吧.
某些情况下, 服务器返回的response是会带有Cache-Control的, 如果这个Cache-Control的时效配置和你想要的不一致, 或是更甚者服务器传回类似这样的:
那么我们就悲剧了, no-cache, 意味着响应不会被缓存.
当然, 如果服务器没有定制response的Cache-Control属性的话, 我们使用addInterceptor来添加拦截器, 还是可以给reponse加入Cache-Control并使其缓存的.
关于Interceptor和NetworkInterceptor的区别, 建议大家还是读源码...在此略过.
稳妥起见, 完全由客户端可控的话, 还是使用addNetworkInterceptor吧.
回顾下, 加入网络缓存的几步:
虽说简单, 但是个中的确包含了很多知识点. Cache-Control属性的使用, 意义; OkHttp的拦截器; Retrofit的header配置等等.
还是那句话, 更多的是希望大家能够在学到东西的同时, 了解更多其相关的原理, 或是学习方法.
本文例子, 完整代码