Android網(wǎng)絡(luò)請求&緩存

本文主要介紹Android網(wǎng)絡(luò)請求中的一些基礎(chǔ)知識(shí)及緩存的應(yīng)用

目錄

http請求&響應(yīng)相關(guān)知識(shí)

okhttp&Interceptor

retrofit+ okhttp + rxjava的緩存實(shí)現(xiàn)

http相關(guān)知識(shí)

直接貼上jude的圖,jude是我的好老師

請求包.png

例子.png

響應(yīng)包.png

例子.png

請求頭描述了客戶端向服務(wù)器發(fā)送請求時(shí)使用的http協(xié)議類型,所使用的編碼,以及發(fā)送內(nèi)容的長度,等等。

相應(yīng)的響應(yīng)頭用來描述服務(wù)器回給你對(duì)所返回的content的一些描述,服務(wù)器類型,我返回的編碼,我返回的內(nèi)容有多長等等。

okhttp

okhttp是現(xiàn)在開發(fā)中相對(duì)成熟的網(wǎng)絡(luò)請求框架,對(duì)比HttpURLConnection有更易用的API和更優(yōu)良的性能。

在這里對(duì)于常規(guī)的get/post 同步/異步的方法就不提了,主要是對(duì)應(yīng)上面的介紹寫一些高級(jí)用法。

Request&Response的header部分

這部分為了下文緩存部分如何添加header做介紹

請求包對(duì)應(yīng)okhttp中的Request,響應(yīng)包對(duì)應(yīng)Response

當(dāng)寫請求頭的時(shí)候,使用header(name, value)可以設(shè)置唯一的name、value。如果已經(jīng)有值,舊的將被移除,然后添加新的。使用addHeader(name, value)

可以添加多值(添加,不移除已有的)。當(dāng)讀取響應(yīng)頭時(shí),使用header(name)

返回最后出現(xiàn)的name、value。通常情況這也是唯一的name、value。如果沒有值,那么header(name)將返回null。如果想讀取字段對(duì)應(yīng)的所有值,使用headers(name)會(huì)返回一個(gè)list。

Interceptor

Interceptor,就像他的翻譯一樣“攔截器”,攔截你的Request,做一些想做的事情再發(fā)送出去。

改寫請求和響應(yīng)

Interceptor interceptor =newInterceptor() {publicResponseintercept(Chain chain)throwsIOException{returnnull;? ? ? ? ? ? }? ? ? ? };

可以通過以下代碼獲取被攔截的Request

Request request = chain.request();

然后可以對(duì)這個(gè)request進(jìn)行newBuilder() 重新產(chǎn)生一個(gè)request發(fā)送出去

調(diào)用以下代碼產(chǎn)生一個(gè)滿足請求的響應(yīng)

Response response = chain.proceed(request);

當(dāng)我們執(zhí)行到proceed,就會(huì)去判斷是否有攔截器,有的話先執(zhí)行攔截器里的intercept,而在intercept里一般會(huì)進(jìn)行一些自定義操作并且調(diào)用procced去判斷是否要繼續(xù)執(zhí)行攔截器操作還是直接去獲取網(wǎng)絡(luò)請求

publicResponseproceed(Request request)throwsIOException{//判斷還有攔截器需要執(zhí)行不,生成新的ApplicationInterceptorChain并調(diào)用它的intercept去執(zhí)行用戶定義的操作if(this.index < Call.this.client.interceptors().size()) {? ? ? ? ? ? ? Call.ApplicationInterceptorChain chain = Call.this.new ApplicationInterceptorChain(this.index +1, request,this.forWebSocket);return((Interceptor)Call.this.client.interceptors().get(this.index)).intercept(chain);? ? ? ? ? }else{returnCall.this.getResponse(request,this.forWebSocket);? ? ? ? ? }? ? ? }

緩存(retrofit+okhttp+rxjava)

app網(wǎng)絡(luò)數(shù)據(jù)的離線緩存實(shí)現(xiàn)有很多種辦法,例如存進(jìn)數(shù)據(jù)庫(保存json使用時(shí)拿出來解析),存專有文件,或者SharedPreference等等,也可以自己實(shí)現(xiàn)LruCache和

DiskLruCache這兩種緩存策略構(gòu)成二級(jí)緩存(內(nèi)存和磁盤)

緩存對(duì)于移動(dòng)端是非常重要的存在。

減少請求次數(shù),減小服務(wù)器壓力.

本地?cái)?shù)據(jù)讀取速度更快,讓頁面不會(huì)空白幾百毫秒。

在無網(wǎng)絡(luò)的情況下提供數(shù)據(jù)。

okhttp的緩存設(shè)計(jì)和瀏覽器的緩存設(shè)計(jì)差不多,可以通過添加響應(yīng)頭的形式進(jìn)行緩存處理。

關(guān)于添加響應(yīng)頭和其他緩存知識(shí)請看這個(gè)鏈接web緩存相關(guān)概念

(筆者還沒看完 = =)

retrofit是依賴okhttp的一套R(shí)ESTful架構(gòu)的Android(Java)客戶端實(shí)現(xiàn)

通過構(gòu)造retrofit時(shí)的.client()方法更改其中的okhttp的實(shí)現(xiàn),從而達(dá)到緩存的效果,在這里不介紹retrofit的具體用法。

下面是一個(gè)例子實(shí)現(xiàn)了有網(wǎng)緩存,無網(wǎng)絡(luò)只讀取緩存

File cacheFile =newFile(APP.getContext().getExternalCacheDir(),"ZhiBookCache");? ? ? ? Cache cache =newCache(cacheFile,1024*1024*50);? ? ? ? Interceptor interceptor =newInterceptor() {@OverridepublicResponseintercept(Chain chain)throwsIOException{? ? ? ? ? ? ? ? Request request = chain.request();if(!HttpUtils.isNetworkConnected(APP.getContext())) {? ? ? ? ? ? ? ? ? ? request = request.newBuilder()? ? ? ? ? ? ? ? ? ? ? ? ? ? .cacheControl(CacheControl.FORCE_CACHE)? ? ? ? ? ? ? ? ? ? ? ? ? ? .build();? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? Response response = chain.proceed(request);if(HttpUtils.isNetworkConnected(APP.getContext())) {intmaxAge =0*60;// 有網(wǎng)絡(luò)時(shí) 設(shè)置緩存超時(shí)時(shí)間0個(gè)小時(shí)response.newBuilder()? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Cache-Control","public, max-age="+ maxAge)? ? ? ? ? ? ? ? ? ? ? ? ? ? .removeHeader("Pragma")// 清除頭信息,因?yàn)榉?wù)器如果不支持,會(huì)返回一些干擾信息,不清除下面無法生效.build();? ? ? ? ? ? ? ? }else{// 無網(wǎng)絡(luò)時(shí),設(shè)置超時(shí)為4周intmaxStale =60*60*24*28;? ? ? ? ? ? ? ? ? ? response.newBuilder()? ? ? ? ? ? ? ? ? ? ? ? ? ? .header("Cache-Control","public, only-if-cached, max-stale="+ maxStale)? ? ? ? ? ? ? ? ? ? ? ? ? ? .removeHeader("Pragma")? ? ? ? ? ? ? ? ? ? ? ? ? ? .build();? ? ? ? ? ? ? ? }returnresponse;? ? ? ? ? ? }? ? ? ? };? ? ? ? client =newOkHttpClient.Builder().cache(cache)? ? ? ? ? ? ? ? .addInterceptor(interceptor)? ? ? ? ? ? ? ? .build();? ? ? ? retrofit =newRetrofit.Builder()? ? ? ? ? ? ? ? .baseUrl(RetrofitAPI.BASIC_DAILY)? ? ? ? ? ? ? ? .addConverterFactory(GsonConverterFactory.create())? ? ? ? ? ? ? ? .addCallAdapterFactory(RxJavaCallAdapterFactory.create())? ? ? ? ? ? ? ? .client(client)? ? ? ? ? ? ? ? .build();? ? ? ? retrofitAPI = retrofit.create(RetrofitAPI.class);

之后調(diào)用下面代碼獲取請求后的序列化對(duì)象

retrofitAPI.getDaily()? ? ? ? ? ? ? ? .subscribeOn(Schedulers.io())? ? ? ? ? ? ? ? .observeOn(AndroidSchedulers.mainThread())? ? ? ? ? ? ? ? .subscribe(newObserver() {@OverridepublicvoidonCompleted(){? ? ? ? ? ? ? ? ? ? }@OverridepublicvoidonError(Throwable e){? ? ? ? ? ? ? ? ? ? ? ? Log.d(TAG,e.getMessage());? ? ? ? ? ? ? ? ? ? }@OverridepublicvoidonNext(DailyBean bean){? ? ? ? ? ? ? ? ? ? ? ? listener.onGetDailySuccess(bean);? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? });

最后附上retrofit接口部分

@GET("news/latest")ObservablegetDaily();

參考文章

Android網(wǎng)絡(luò)請求心路歷程

Retrofit 源碼解讀之離線緩存策略的實(shí)現(xiàn)

OkHttp源碼解析

OkHttp使用進(jìn)階

作者:srtianxia

鏈接:http://m.itdecent.cn/p/42a396430be5

來源:簡書

簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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