retrofit2 + okhttp3 緩存實踐 及 must-revalidate 過濾

需求

  • 手機無網(wǎng)絡時能查看緩存數(shù)據(jù)
  • 有些數(shù)據(jù)變動較小,不必每次重新請求,緩解服務器壓力

結(jié)果

  • 所有返回均自動緩存,無網(wǎng)絡時默認使用緩存數(shù)據(jù) (如果有)
  • 所有請求默認復用時間為 10s,復用時間內(nèi)新的請求不訪問服務器,使用緩存數(shù)據(jù) (如果有)
  • 可針對不同接口設置復用時間,也可不復用 (設置為 0s)

條件

GET請求

實現(xiàn)

  • 設置緩存存儲位置及大小
Cache cache = new Cache(new File(getCacheDir(mContext), "responses"), 1024 * 1024 * 50)
  • 自定義緩存攔截器
public class OKHttpCacheInterceptor implements Interceptor {

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        if (!isNetworkAvailable(App.getApplication())) {
            // 網(wǎng)絡不可用時強制使用緩存
            request = request.newBuilder()
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build();
        } else if (TextUtils.isEmpty(request.header("Cache-Control"))) {
            // 網(wǎng)絡可用 && 未設置復用時間 -> 默認復用時間為 10s
            request = request.newBuilder()
                    .header("Cache-Control", "private, max-stale=10")
                    .build();
        }
        Response response = chain.proceed(request);
        if (response.code() == 504) {
            throw new IOException("網(wǎng)絡連接不可用");
        }
        return response.newBuilder()
                .removeHeader("Pragma")
                .build();
    }

    /**
     * 判斷網(wǎng)絡是否有效
     */
    private boolean isNetworkAvailable(Context context) {
        NetworkInfo netInfo = getNetworkInfo(context);
        return netInfo != null && netInfo.isAvailable();
    }

    /**
     * 獲取當前網(wǎng)絡信息
     */
    private NetworkInfo getNetworkInfo(Context context) {
        if (null != context) {
            ConnectivityManager mConnectivityManager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            return mConnectivityManager.getActiveNetworkInfo();
        }
        return null;
    }
}
  • 創(chuàng)建客戶端實例
new OkHttpClient.Builder()
    .addInterceptor(new OKHttpCacheInterceptor ())
    .cache(cache)
    .build()
  • Retrofit 初始化
ClientAPI api = new Retrofit.Builder()
    .baseUrl(BASE_URL) 
    .addConverterFactory(converterFactory)
    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
    .client(client)
    .build()
    .create(ClientAPI.class);
  • API接口
public interface ClientAPI {

    /**
     * get 
     *
     * @return Daily
     */
    // 指定返回復用時間為 60s
    @Headers("Cache-Control: max-stale=60")
    @GET("news/latest")
    Observable<Daily> getDaily();

    ...
}
  • 使用
api.getDaily()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(daily -> {
        ...
     }, e -> Snackbar.make(binding.recycler, e.getMessage(), Snackbar.LENGTH_INDEFINITE).show());
  • 補充
    當服務器返回Cache-Control: must-revalidate時無法緩存,此時需加上另外一個網(wǎng)絡攔截器(慎用
@Override
  public Response intercept(Chain chain) throws IOException {
    return chain.proceed(chain.request())
        .newBuilder()
        .removeHeader("Pragma")
        .removeHeader("Cache-Control")
        .build();
  }
addNetworkInterceptor(new OKHttpCacheNetworkInterceptor())
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容