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