Retrofit2.0+okhttp3快取策略
2017.04.09 17:59* 字數 445 閱讀 590評論 1喜歡 0
概述
- Retrofit本身是沒有快取的,如果想設定快取功能,需要在http client層知道HTTP的語義。
- okhttp是square公司釋出的一個HTTP client,它支援快取記憶體伺服器響應的語義。
- 使用場景:提高使用者體驗,降低伺服器的負荷。無網路的條件下,讀取快取;有網條件下,對非實時性的資料可以在規定的時間裡讀取快取,例如設定時間為60s,實時性的資料還是要每次都獲取最新資料。
封裝Retrofit管理類
public class RetrofitManger { private static RetrofitManger mInstance; public static boolean isDebug = false; public static synchronized RetrofitManger getInstance() { if (mInstance == null) mInstance = new RetrofitManger(); return mInstance; } public void deBug(boolean isDebug) { this.isDebug = isDebug; } // create retrofit singleton private Retrofit createApiClient(String baseUrl) { return new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(createOkHttpClient(isDebug)) .build(); } // create okHttpClient singleton OkHttpClient createOkHttpClient(boolean debug) { //設定快取100M Cache cache = new Cache(new File(MainApplication.getContext().getCacheDir(),"httpCache"),1024 * 1024 * 100); return new OkHttpClient.Builder() .cache(cache) .addNetworkInterceptor(new HttpCacheInterceptor()) .addInterceptor( new HttpLoggingInterceptor().setLevel( debug ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE)) .build(); } }
HttpCacheInterceptor類
public class HttpCacheInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (!NetWorkHelper.isNetConnected(MainApplication.getContext())) { request = request.newBuilder() .cacheControl(CacheControl.FORCE_CACHE) .build(); } Response response = chain.proceed(request); if (NetWorkHelper.isNetConnected(MainApplication.getContext())) { int maxAge = 60 * 60; // read from cache for 1 minute response.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, max-age=" + maxAge) .build(); } else { int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale response.newBuilder() .removeHeader("Pragma") .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return response; } }
有網路的情況下設定max-age=60 x 60,即1分鐘;沒有網路的情況下設定max-stale=60 x 60 x 24 x 28,即4周。
okhttp3 中Cache類包含的快取策略
noCache :不使用快取,全部走網路
noStore : 不使用快取,也不儲存快取
onlyIfCached : 只使用快取
maxAge :設定最大失效時間,失效則不使用
maxStale :設定最大失效時間,失效則不使用
minFresh :設定最小有效時間,失效則不使用
FORCE_NETWORK : 強制走網路
FORCE_CACHE :強制走快取
單個介面設定快取
上面介紹的都是統一設定快取,Retrofit還可以為單個介面設定快取。
配置單個請求的@Headers,設定此請求的快取策略不影響其他請求的快取策略,不設定則沒有快取。
// 設定單個請求的快取時間
@Headers("Cache-Control: max-age=640000")
@GET("user/list")
Call<List<javaBean>> getList();
讀取單個介面的@Headers配置
String cacheControl = request.cacheControl().toString();
response.newBuilder()
.header("Cache-Control", cacheControl)
.removeHeader("Pragma")
.build();
快取策略互動 — 最長使用期限和最長過期時間
為了幫助確保將最新鮮的內容返回給客戶端應用程式,客戶端快取策略和伺服器重新驗證要求的互動始終會造成最保守的快取策略。 本主題中的所有示例闡明針對在 1 月 1 日快取、1 月 4 日過期的資源的快取策略。
在以下示例中,結合使用了最長過期時間值 (maxStale
) 與最長使用時間 (maxAge
):
-
如果快取策略設定
maxAge
= 5 天,且未指定maxStale
值,根據maxAge
值,此內容在 1 月 6 日前可用。 但是,根據伺服器的重新驗證要求,內容會在 1 月 4 日過期。 因為內容過期日期更保守(更早),所以它優先於maxAge
策略。 因此,即使尚未達到最長使用時間,此內容在 1 月 4 日便會過期,並且必須進行重新驗證。 -
如果快取策略設定
maxAge
= 5 天,maxStale
= 3 天,根據maxAge
值,此內容在 1 月 6 日前可用。 根據maxStale
值,此內容在 1 月 7 日前可用。 因此,會在 1 月 6 日重新驗證此內容。 -
如果快取策略設定
maxAge
= 5 天,maxStale
= 1 天,根據maxAge
值,此內容在 1 月 6 日前可用。 根據maxStale
值,此內容在 1 月 5 日前可用。 因此,會在 1 月 5 日重新驗證此內容。
當內容的最長使用時間小於過期日期時,更保守的快取行為佔據優先順序,且最長過期時間值不會有任何效果。 以下示例闡明瞭在內容過期之前到達最長使用時間 (maxAge
) 時設定最長過期時間 (maxStale
) 值的效果:
-
如果快取策略設定
maxAge
= 1 天,且未指定maxStale
值,即使內容尚未過期,也會在 1 月 2 日重新驗證此內容。 -
如果設快取策略設定
maxAge
= 1 天,maxStale
= 3 天,會在 1 月 2 日重新驗證此內容以強制實施更保守的策略設定。 -
如果快取策略設定
maxAge
= 1 天,maxStale
= 1 天,會在 1 月 2 日重新驗證此內容。