diff --git a/README.md b/README.md index 40999b4..7625101 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,146 @@ 一些与业务相关的okhttp拦截器 -## 介绍 +## 导入 -*com.huburt.interceptors.CacheInterceptor* +项目的build.gradle添加: + +``` +allprojects { + repositories { + ... + maven { url 'https://jitpack.io' } + } +} +``` + +### com.huburt.interceptors.CacheInterceptor + +#### 介绍 okhttp自带的CacheInterceptor只能缓存GET请求,并且需要服务端的支持(或者自定义拦截器模拟服务端支持)。 -而有时候出于业务或者其他的因素,我们需要在app端控制缓存,并且 +而有时候出于业务或者其他的因素,我们需要在app端控制缓存,并且可能还需要缓存post请求。 +因此本人写了一个CacheInterceptor用于实现以上需求。 + +#### 使用 + +com.huburt.interceptors.CacheInterceptor是一个抽象类,使用时可以直接使用默认实现。 +首先我们向okhttp的client添加我们的CacheInterceptor的默认实现: + +``` +client = new OkHttpClient.Builder() + .addInterceptor(CacheInterceptor.getDefault(context)) + .build(); +``` +其次在需要缓存的请求上添加header: +``` +Request request = new Request.Builder() + .url("http://www.baidu.com") + .addHeader(CacheInterceptor.HEADER_NAME, String.valueOf(60)) + .build(); +``` +``` +@Headers({CacheInterceptor.HEADER_NAME + ":60"}) +@GET("users/{user}/repos") +Call listRepos(@Path("user") String user); +``` +header的key为CacheInterceptor.HEADER_NAME,value为缓存时间,单位是毫秒 + + +#### 缓存逻辑 + +``` +@Override +public Response intercept(Chain chain) throws IOException { + Request request = chain.request(); + //读取指定header + String header = request.header(HEADER_NAME); + //不为空,表示需要缓存 + if (!TextUtils.isEmpty(header)) { + //获取缓存的key,get等请求为url,post等请求为url+requestBody 取md5 + String key = getCacheKey(request); + //获取缓存 + T cache = getCache(key); + //判断缓存时候可用 + if (checkUseful(cache)) {//缓存可用,从缓存中创建Response对象 + return createResponseFromCache(request, cache); + } else {//缓存不可用,走网络 + Response response = chain.proceed(request); + if (response.isSuccessful()) {//如果接口请求成功,则缓存结果 + int cacheTime = parseCacheTime(header); + saveAsCache(key, convert(response), cacheTime); + } + return response; + } + } + //没有header,表示不需要缓存,不做处理 + return chain.proceed(request); +} +``` + +#### 扩展 + +默认实现是将ResponseBody转换成String,缓存到cache磁盘。 +如果不喜欢默认实现的缓存,也可以自己继承CacheInterceptor实现自己的缓存逻辑。 +需要实现以下几个方法,其中T为泛型,表示缓存实体的类型: +``` + /** + * @param request okhttp request + * @param cache the cache from {@link CacheInterceptor#getCache} and checked useful + * @return response for okhttp + */ + protected abstract Response createResponseFromCache(Request request, T cache); + + /** + * @param cache the cache from {@link CacheInterceptor#getCache} + * @return true if the cache is useful or false + */ + protected abstract boolean checkUseful(T cache); + + /** + * use default cache time when the cache header set with wrong content. + * you can override this method return your custom default cache time. + * + * @return time in minutes + */ + public int defaultCacheTime() { + return 60; + } + + /** + * get cache by key + * + * @param key key of cache + * @return cache or null + */ + public abstract T getCache(String key); + + /** + * convert response to your custom cache entity + * + * @param response okhttp response + * @return cache entity + */ + protected abstract T convert(Response response); + + /** + * save the cache entity + * + * @param key MD5 of url (if request method is post or patch ,key is url + requestBody) + * @param cacheEntity custom entity + * @param cacheTime cache time (minutes) + */ + protected abstract void saveAsCache(String key, T cacheEntity, int cacheTime); + + /** + * remove cache by key + * + * @param key key of cache + */ + public abstract void removeCache(T key); + + /** + * clear all cache of http + */ + public abstract void clearCache(); +``` \ No newline at end of file diff --git a/build.gradle b/build.gradle index 43c0708..429c1a8 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { classpath 'com.android.tools.build:gradle:3.1.3' - + classpath 'com.github.dcendents:android-maven-gradle-plugin:2.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/interceptors/build.gradle b/interceptors/build.gradle index fa70ab7..435e4a7 100644 --- a/interceptors/build.gradle +++ b/interceptors/build.gradle @@ -1,4 +1,7 @@ apply plugin: 'com.android.library' +apply plugin: 'com.github.dcendents.android-maven' + +group = 'com.github.huburt-Hu' android { compileSdkVersion 27 diff --git a/interceptors/src/main/java/com/huburt/interceptors/LogInterceptor.java b/interceptors/src/main/java/com/huburt/interceptors/LogInterceptor.java index a0ea450..1d9969f 100644 --- a/interceptors/src/main/java/com/huburt/interceptors/LogInterceptor.java +++ b/interceptors/src/main/java/com/huburt/interceptors/LogInterceptor.java @@ -19,25 +19,31 @@ public class LogInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); + printRequest(request); long t1 = System.nanoTime(); - - Buffer buffer = new Buffer(); - RequestBody body = request.body(); - if (body != null) - body.writeTo(buffer); - Log.e(HTTP_LOG, String.format("Sending request %s on %s %n%s Request Params: %s", - request.url(), chain.connection(), request.headers(), buffer.clone().readUtf8())); - buffer.close(); - Response response = chain.proceed(request); long t2 = System.nanoTime(); + double takeTime = (t2 - t1) / 1e6d; + printResponse(response, takeTime); + return response; + } + protected void printResponse(Response response, double takeTime) throws IOException { BufferedSource source = response.body().source(); source.request(Long.MAX_VALUE); - buffer = source.buffer().clone(); + Buffer buffer = source.buffer().clone(); Log.e(HTTP_LOG, String.format("Received response for %s in %.1fms \ncode:%s %n%s Response Json: %s", - response.request().url(), (t2 - t1) / 1e6d, response.code(), response.headers(), + response.request().url(), takeTime, response.code(), response.headers(), buffer.readUtf8())); - return response; + } + + protected void printRequest(Request request) throws IOException { + Buffer buffer = new Buffer(); + RequestBody body = request.body(); + if (body != null) + body.writeTo(buffer); + Log.e(HTTP_LOG, String.format("Sending request %s %n%s Request Params: %s", + request.url(), request.headers(), buffer.clone().readUtf8())); + buffer.close(); } }