使用ReTrofit做緩存(結合上拉加載和下拉刷新)


1. noCache 不使用緩存,全部走網絡

2. noStore 不使用緩存,也不存儲緩存

3. onlyIfCached 只使用緩存

4. maxAge 設置最大失效時間,失效則不使用 需要服務器配合

5. maxStale 設置最大失效時間,失效則不使用 需要服務器配合 感覺這兩個類似 還沒怎么弄清楚,清楚的同學歡迎留言

6. minFresh 設置有效時間,依舊如上

7. FORCE_NETWORK 只走網絡

8. FORCE_CACHE 只走緩存

結合推酷和簡書看

Cache-Control: no-cache  在請求頭中的意思是:不去拿緩存的數據,直接去訪問服務器的數據。  在響應頭中的意思是:服務器允許客戶端緩存,但是必須先驗證一下(和 no-store的區別)

Cache-Control: max-age=300 在請求頭中表示:第一次訪問服務器獲取數據之后,300秒之內再訪問時,直接走緩存,超過300秒再去請求服務器

              在響應頭中表示:300秒之內,從服務器的緩存中回給客戶端,300秒后從真正的數據中回給客戶端

在響應頭中,Cache-Control參數的 no-cache,表示客戶端仍然可以緩存,但是緩存時要評估下有效性(?)

相應的,在響應頭中,no-store,表示客戶端一定無法緩存,注意兩者區別.

  用ReTrofit做緩存時,使用的OkHttp的攔截器,在ReTrofit初始化中進行設置

//構造函數
public
WebControl_Retrofit(){ init(); }
public void init() {
        Log.d("OkHttp","ReTrofit init");
        HttpLoggingInterceptor logging = new HttpLoggingInterceptor();//添加訪問網絡的日志
        logging.setLevel(HttpLoggingInterceptor.Level.BODY);//日志級別
        OkHttpClient httpClient = new OkHttpClient();

        //緩存路徑
        File cacheFile = new File(UIUtils.getContext().getCacheDir().getAbsolutePath(), "HttpCache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 100);//緩存文件為100MB
        httpClient.setCache(cache);

        Interceptor netInterceptor = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if(!UIUtils.isNetworkReachable(UIUtils.getContext())){//如果網絡不可用
                    request=request.newBuilder()
                            .cacheControl(CacheControl.FORCE_CACHE)
                            .build();
                    Log.d("OkHttp","網絡不可用請求攔截");
                }else{//網絡可用
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_NETWORK)
                            .build();
                    Log.d("OkHttp","網絡可用請求攔截");
                }
                Response response = chain.proceed(request);
                if(UIUtils.isNetworkReachable(UIUtils.getContext())){//如果網絡可用
                    Log.d("OkHttp","網絡可用響應攔截");
                    response= response.newBuilder()
                            //覆蓋服務器響應頭的Cache-Control,用我們自己的,因為服務器響應回來的可能不支持緩存
                            .header("Cache-Control", "public,max-age=2")
                            .removeHeader("Pragma")
                            .build();
                }else{
//                    Log.d("OkHttp","網絡不可用響應攔截");
//                    int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
//                    response= response.newBuilder()
//                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
//                            .removeHeader("Pragma")
//                            .build();
                }
                return response;

            }
        };
        httpClient.interceptors().add(netInterceptor);//添加本地緩存攔截器,用來攔截本地緩存
        httpClient.networkInterceptors().add(netInterceptor);//添加網絡攔截器,用來攔截網絡數據
        httpClient.interceptors().add(logging);  // <-- this is the important line!


        mRetro = new Retrofit.Builder()
                .baseUrl(Web_GlobalConstant.SERVER_URL)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(retrofit.RxJavaCallAdapterFactory.create())
                .client(httpClient)
                .build();
    }

 ReTrofit是根據請求服務器的URL去創建緩存文件,請求的URL不同,所創建的緩存文件也不同,在發起訪問服務器請求時,Retrofit根據URL去找對應的緩存,然后返回緩存的數據

刷新和加載更多的思路:讓服務器給每一條數據做一個時間戳標記,回過來數據時放在Json里,客戶端的請求URL中加一個時間戳參數,下拉刷新時,客戶端傳時間戳為0,表示請求最新的20條數據(假設以20條為單位),請求后ReTrofit根據URL把最新20條數據緩存起來,以請求朋友圈為例子,那么朋友圈緩存文件里只有一個文件,那就是最新的20條數據,並且永遠會這樣,把傳過來的最后一條數據的時間戳記下來,等到上拉加載時,把這個時間戳參數傳過去,然后服務器再把這個時間戳對應數據的之后20條數據回過來,如此循環,這樣就能保證數據完整性,上拉加載更多的數據不需要緩存,只緩存最新的20條數據,服務器是以時間倒序存儲的數據

 

做個筆記:static修飾的變量,在應用程序沒有完全被清理時,會一直保持引用

 

這里是我的GitHub地址,里面有我自己做的一些有用的Demo,適合新手學習,歡迎大家star我的項目 https://github.com/gnehsuy


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM