okhttp3.4.1+retrofit2.1.0實現離線緩衝,retrofitokhttp緩衝

來源:互聯網
上載者:User

okhttp3.4.1+retrofit2.1.0實現離線緩衝,retrofitokhttp緩衝

關於Retrofit+OkHttp的強大這裡就不多說了,還沒瞭解的同學可以自行去百度。這篇文章主要講如何利用Retrofit+OkHttp來實現一個較為簡單的緩衝策略:
即有網環境下我們請求資料時,如果沒有緩衝或者緩衝到期了,就去伺服器拿資料,並且將新緩衝儲存下來,如果有緩衝而且沒有到期,則直接使用緩衝。無網環境下我們請求資料時,緩衝沒到期則直接使用緩衝,緩衝到期了則無法使用,需要重新連網擷取伺服器資料。

緩衝處理還是很有必要的,它有效減少伺服器負荷,降低延遲提升使用者體驗,同時也方便使用者即使在沒網路的情況下也能使用APP。

之前一直有一個疑惑,既然Retrofit已經是對OkHttp的一個封裝了,為什麼還一直說Retrofit+OkHttp要一起搭配使用,後來才知道其實OKHttp很重要的一個作用,就是對一些網路請求的配置,例如連線逾時,讀取逾時,以及一些緩衝配置等。

 

一、添加依賴
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

 

二、配置OkHttpClient(設定緩衝路徑和快取檔案大小) 

File httpCacheDirectory = new File(Environment.getExternalStorageDirectory(), "HttpCache");//這裡為了方便直接把檔案放在了SD卡根目錄的HttpCache中,一般放在context.getCacheDir()中int cacheSize = 10 * 1024 * 1024;//設定快取檔案大小為10MCache cache = new Cache(httpCacheDirectory, cacheSize);httpClient = new OkHttpClient.Builder()             .connectTimeout(10, TimeUnit.SECONDS)//設定連線逾時             .readTimeout(10, TimeUnit.SECONDS)//讀取逾時             .writeTimeout(10, TimeUnit.SECONDS)//寫入逾時             .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)//添加自訂緩衝攔截器(後面講解),注意這裡需要使用.addNetworkInterceptor             .cache(cache)//把緩衝添加進來             .build();

 

三、配置Retrofit

retrofit = new Retrofit.Builder()                .baseUrl(baseUrl)                .client(httpClient)//把OkHttpClient添加進來                .addConverterFactory(GsonConverterFactory.create())                .build();

 

四、編寫攔截器

  我們知道其實Retrofit+OkHttp的緩衝主要通過攔截器實現,所以主要做的功夫也在攔截器裡面。

 static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {        @Override        public Response intercept(Chain chain) throws IOException {            Request request = chain.request();            //網上很多範例程式碼都對在request請求前對其進行無網的判斷,其實無需判斷,無網自動訪問緩衝//            if(!NetworkUtil.getInstance().isConnected()){//                request = request.newBuilder()//                        .cacheControl(CacheControl.FORCE_CACHE)//只訪問緩衝//                        .build();//            }            Response response = chain.proceed(request);            if (NetworkUtil.getInstance().isConnected()) {                int maxAge = 60;//緩衝失效時間,單位為秒                return response.newBuilder()                        .removeHeader("Pragma")//清除頭資訊,因為伺服器如果不支援,會返回一些幹擾資訊,不清除下面無法生效                        .header("Cache-Control", "public ,max-age=" + maxAge)                        .build();            } else {                //這段代碼設定無效//                int maxStale = 60 * 60 * 24 * 28; // 無網路時,設定逾時為4周//                return response.newBuilder()//                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)//                        .removeHeader("Pragma")//                        .build();            }            return response;        }    };

到這裡,其實已經可以實現了我們開頭所說的緩衝效果了。

  但是,上面設定的每個介面緩衝時間都一樣,例如我現在想讓不同介面的快取資料失效時間都不一樣,甚至有些介面不快取資料,應該怎麼做呢?其實也很簡單

首先我們只需要在介面前面添加@Headers參數(max-age代表緩衝時間,單位為秒,樣本中表示緩衝失效時間為60s,想要多少時間可以自行設定),不設定@Headers參數則不進行緩衝。

    @Headers("Cache-Control:public ,max-age=60")    @GET("getBusiness.action")//商店資訊    Call<RestaurantInfoModel> getRestaurantInfo(@Query("userId") String userId,@Query("businessId") String businessId);

 同時,我們的緩衝攔截器也要做下簡單的修改(去掉了之前的注釋代碼)

    static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {        @Override        public Response intercept(Chain chain) throws IOException {            Request request = chain.request();            Response response = chain.proceed(request);            if (NetworkUtil.getInstance().isConnected()) {                //擷取頭部資訊                String cacheControl =request.cacheControl().toString();                return response.newBuilder()                        .removeHeader("Pragma")//清除頭資訊,因為伺服器如果不支援,會返回一些幹擾資訊,不清除下面無法生效                        .header("Cache-Control", cacheControl)                        .build();            }            return response;        }    };

 

*注意:

1.只能緩衝Get請求的介面,不能緩衝Post請求的介面

2.OkHttpClient需要用.addNetworkInterceptor添加緩衝攔截器,不能使用.addInterceptor,也無需兩者同時使用。

3.此方法無需伺服器端任何操作,適用於伺服器端沒有其他緩衝策略,如果伺服器端有自己的緩衝策略代碼應該做相應的修改,以適應伺服器端。

 

附上所有代碼:

/** * 簡單封裝的Retroit初始化類 */public class initRetrofit {    private static String baseUrl = "http://202.171.212.154:8080/hh/";    private static OkHttpClient httpClient;    private static Retrofit retrofit;    public static Retrofit initRetrofit() {        //緩衝路徑和大小        File httpCacheDirectory = new File(Environment.getExternalStorageDirectory(), "HttpCache");        int cacheSize = 10 * 1024 * 1024;        Cache cache = new Cache(httpCacheDirectory, cacheSize);        //日誌攔截器        HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();        interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);        httpClient = new OkHttpClient.Builder()                .connectTimeout(10, TimeUnit.SECONDS)//設定連線逾時                .readTimeout(10, TimeUnit.SECONDS)//讀取逾時                .writeTimeout(10, TimeUnit.SECONDS)//寫入逾時                .addInterceptor(interceptor)//添加日誌攔截器                .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR)//添加緩衝攔截器                .cache(cache)//把緩衝添加進來                .build();        retrofit = new Retrofit.Builder()                .baseUrl(baseUrl)                .client(httpClient)                .addConverterFactory(GsonConverterFactory.create())                .build();        return retrofit;    }    public static RetrofitAPI getService() {        return initRetrofit().create(RetrofitAPI.class);    }//    //緩衝攔截器,不同介面不同緩衝//    static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {//        @Override//        public Response intercept(Chain chain) throws IOException {////            Request request = chain.request();//            Response response = chain.proceed(request);////            if (NetworkUtil.getInstance().isConnected()) {//                String cacheControl =request.cacheControl().toString();//                return response.newBuilder()//                        .removeHeader("Pragma")//清除頭資訊,因為伺服器如果不支援,會返回一些幹擾資訊,不清除下面無法生效//                        .header("Cache-Control", cacheControl)//                        .build();//            }//            return response;//        }//    };    //緩衝攔截器,統一緩衝60s    static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {        @Override        public Response intercept(Chain chain) throws IOException {            Request request = chain.request();            Response response = chain.proceed(request);            if (NetworkUtil.getInstance().isConnected()) {                int maxAge = 60*60*24*2;//緩衝失效時間,單位為秒                return response.newBuilder()                        .removeHeader("Pragma")//清除頭資訊,因為伺服器如果不支援,會返回一些幹擾資訊,不清除下面無法生效                        .header("Cache-Control", "public ,max-age=" + maxAge)                        .build();            }            return response;        }    };}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.