OkHttp攔截器在Android網(wǎng)絡(luò)中的使用和工作原理
什么是OkHttp攔截器
OkHttp攔截器是一種機(jī)制,允許您在網(wǎng)絡(luò)請(qǐng)求和響應(yīng)的傳輸過程中執(zhí)行自定義操作。它們通常用于記錄請(qǐng)求日志、修改請(qǐng)求頭、緩存響應(yīng)或進(jìn)行身份驗(yàn)證等操作。攔截器可以按照添加它們的順序依次執(zhí)行,從而形成一個(gè)攔截器鏈。
攔截器鏈
攔截器鏈?zhǔn)且粋€(gè)由多個(gè)攔截器組成的鏈條,每個(gè)攔截器在請(qǐng)求和響應(yīng)的傳輸過程中都有機(jī)會(huì)進(jìn)行操作。這些攔截器按照它們添加的順序執(zhí)行,因此順序很重要。以下是一個(gè)攔截器鏈的示意圖:
Request 1 -> Interceptor 1 -> Interceptor 2 -> ... -> Interceptor N -> Server
<- <- ... <- <-
Response 1 <- Interceptor 1 <- Interceptor 2 <- ... <- Interceptor N <- ServerOkHttp中攔截器的工作原理
OkHttp的核心組件是Interceptor接口和RealCall類。Interceptor接口定義了intercept()方法,它接收一個(gè)Chain對(duì)象作為參數(shù),該對(duì)象用于執(zhí)行攔截器鏈上的操作。RealCall類用于實(shí)際執(zhí)行網(wǎng)絡(luò)請(qǐng)求并管理攔截器鏈的執(zhí)行。
創(chuàng)建OkHttpClient
首先,您需要?jiǎng)?chuàng)建一個(gè)OkHttpClient實(shí)例,該實(shí)例用于發(fā)起網(wǎng)絡(luò)請(qǐng)求,并配置攔截器鏈。
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new CustomInterceptor())
.build();發(fā)起網(wǎng)絡(luò)請(qǐng)求
當(dāng)您調(diào)用client.newCall(request)來創(chuàng)建一個(gè)新的網(wǎng)絡(luò)請(qǐng)求時(shí),OkHttp會(huì)創(chuàng)建一個(gè)RealCall對(duì)象,該對(duì)象代表了實(shí)際的網(wǎng)絡(luò)請(qǐng)求。接下來,RealCall會(huì)執(zhí)行攔截器鏈上的操作。
Request request = new Request.Builder()
.url("https://example.com/api")
.build();
Call call = client.newCall(request);
Response response = call.execute();攔截器鏈執(zhí)行
攔截器鏈的執(zhí)行是在RealCall類中完成的,它遍歷攔截器列表并按照添加順序依次執(zhí)行。以下是相關(guān)源碼示例:
public Response getResponseWithInterceptorChain() throws IOException {
// 創(chuàng)建一個(gè)初始的Interceptor.Chain
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
interceptors.add(new CallServerInterceptor(false));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, 0, originalRequest, this, callStackTrace);
// 依次執(zhí)行攔截器
return chain.proceed(originalRequest);
}Interceptor.Chain的實(shí)現(xiàn)
RealInterceptorChain類實(shí)現(xiàn)了Interceptor.Chain接口,它包含了當(dāng)前請(qǐng)求的信息,并負(fù)責(zé)執(zhí)行攔截器鏈上的操作。在proceed()方法中,它依次調(diào)用攔截器的intercept()方法,將請(qǐng)求傳遞給下一個(gè)攔截器,并最終返回響應(yīng)。
public Response proceed(Request request) throws IOException {
// 執(zhí)行下一個(gè)攔截器或者發(fā)起網(wǎng)絡(luò)請(qǐng)求
if (index >= interceptors.size()) throw new AssertionError();
calls++;
if (chain == null) throw new IllegalStateException("Check failed.");
if (eventListener != null) {
eventListener.callStart(this);
}
// 獲取當(dāng)前攔截器
Interceptor interceptor = interceptors.get(index++);
// 調(diào)用攔截器的intercept方法,將請(qǐng)求傳遞給下一個(gè)攔截器或者執(zhí)行網(wǎng)絡(luò)請(qǐng)求
Response response = interceptor.intercept(this);
if (eventListener != null) {
eventListener.callEnd(this);
}
return response;
}編寫自定義攔截器
要編寫自定義攔截器,首先需要實(shí)現(xiàn)Interceptor接口,并實(shí)現(xiàn)intercept()方法。這個(gè)方法接收一個(gè)Chain對(duì)象作為參數(shù),允許您訪問和操作請(qǐng)求和響應(yīng)。
public class CustomInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
// 在請(qǐng)求前執(zhí)行的代碼
Request originalRequest = chain.request();
// 可以修改請(qǐng)求
Request modifiedRequest = originalRequest.newBuilder()
.addHeader("Authorization", "Bearer YourAccessToken")
.build();
// 執(zhí)行請(qǐng)求
Response response = chain.proceed(modifiedRequest);
// 在響應(yīng)后執(zhí)行的代碼
// 可以修改響應(yīng)
return response;
}
}實(shí)際應(yīng)用示例
以下是一些實(shí)際運(yùn)用示例,展示了如何使用OkHttp攔截器來實(shí)現(xiàn)不同的功能
日志記錄
這個(gè)攔截器用于記錄請(qǐng)求和響應(yīng)的詳細(xì)信息,有助于調(diào)試和排查問題。
public class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long startTime = System.nanoTime();
Log.d("OkHttp", String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long endTime = System.nanoTime();
Log.d("OkHttp", String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (endTime - startTime) / 1e6d, response.headers()));
return response;
}
}身份驗(yàn)證
這個(gè)攔截器用于在每個(gè)請(qǐng)求中添加身份驗(yàn)證標(biāo)頭,以確保請(qǐng)求是經(jīng)過身份驗(yàn)證的。
public class AuthInterceptor implements Interceptor {
private final String authToken;
public AuthInterceptor(String authToken) {
this.authToken = authToken;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
// 添加身份驗(yàn)證標(biāo)頭
Request authenticatedRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer " + authToken)
.build();
return chain.proceed(authenticatedRequest);
}
}緩存
這個(gè)攔截器用于實(shí)現(xiàn)響應(yīng)緩存,以減少對(duì)服務(wù)器的請(qǐng)求。
public class CacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// 在這里檢查是否有緩存可用,如果有,返回緩存的響應(yīng)
Response response = chain.proceed(request);
// 在這里將響應(yīng)緩存起來
return response;
}
}請(qǐng)求重試
這個(gè)攔截器用于處理請(qǐng)求失敗時(shí)的重試邏輯。
public class RetryInterceptor implements Interceptor {
private final int maxRetryCount;
public RetryInterceptor(int maxRetryCount) {
this.maxRetryCount = maxRetryCount;
}
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = null;
IOException lastException = null;
for (int retryCount = 0; retryCount < maxRetryCount; retryCount++) {
try {
response = chain.proceed(request);
if (response.isSuccessful()) {
return response;
}
} catch (IOException e) {
lastException = e;
}
}
// 如果達(dá)到最大重試次數(shù)仍然失敗,拋出異常
throw lastException;
}
}自定義響應(yīng)處理
這個(gè)攔截器用于在接收到響應(yīng)后執(zhí)行自定義的響應(yīng)處理邏輯。
public class ResponseProcessingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
// 在這里對(duì)響應(yīng)進(jìn)行自定義處理
return response;
}
}錯(cuò)誤處理
這個(gè)攔截器用于處理一些常見的錯(cuò)誤情況
public class ErrorHandlingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
try {
Response response = chain.proceed(request);
// 檢查響應(yīng)是否成功
if (!response.isSuccessful()) {
// 在這里處理錯(cuò)誤,可以拋出自定義異常
throw new MyHttpException(response.code(), response.message());
}
return response;
} catch (IOException e) {
// 在這里處理網(wǎng)絡(luò)連接錯(cuò)誤
throw new MyNetworkException(e.getMessage(), e);
}
}
}重定向請(qǐng)求
這個(gè)攔截器用于自定義重定向行為
public class RedirectInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
// 檢查是否是重定向響應(yīng)
if (response.isRedirect()) {
String newUrl = response.header("Location");
if (newUrl != null) {
// 構(gòu)建新的請(qǐng)求并繼續(xù)
Request newRequest = request.newBuilder()
.url(newUrl)
.build();
response = chain.proceed(newRequest);
}
}
return response;
}
}結(jié)論
OkHttp攔截器是Android應(yīng)用程序中處理網(wǎng)絡(luò)請(qǐng)求的有力工具。通過創(chuàng)建自定義攔截器,您可以在請(qǐng)求和響應(yīng)的傳輸過程中執(zhí)行各種操作,以優(yōu)化您的應(yīng)用程序。無論是日志記錄、身份驗(yàn)證、緩存還是其他操作,攔截器都可以幫助您更好地控制和定制網(wǎng)絡(luò)請(qǐng)求流程。
以上就是OkHttp攔截器在Android網(wǎng)絡(luò)中的使用和工作原理的詳細(xì)內(nèi)容,更多關(guān)于OkHttp攔截器在Android中的使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Android入門之使用OKHttp多線程下載文件
- Android 使用 okhttp3和retrofit2 進(jìn)行單文件和多文件上傳
- Android基于OkHttp實(shí)現(xiàn)文件上傳功能
- Android使用OKhttp3實(shí)現(xiàn)登錄注冊(cè)功能+springboot搭建后端的詳細(xì)過程
- Android的簡(jiǎn)單前后端交互(okHttp+springboot+mysql)
- Android Okhttp斷點(diǎn)續(xù)傳面試深入解析
- Android使用OkHttp發(fā)送post請(qǐng)求
- Android使用OkHttp進(jìn)行網(wǎng)絡(luò)同步異步操作
- Android視頻/音頻緩存框架AndroidVideoCache(Okhttp)詳解
- Android OkHttp實(shí)現(xiàn)全局過期token自動(dòng)刷新示例
- OkHttp原理分析小結(jié)
相關(guān)文章
完美解決EditText和ScrollView的滾動(dòng)沖突(上)
這篇文章主要為大家詳細(xì)介紹了完美解決EditText和ScrollView滾動(dòng)沖突的方法,感興趣的小伙伴們可以參考一下2016-06-06
Cocos2d-x 3.0中集成社交分享ShareSDK的詳細(xì)步驟和常見問題解決
這篇文章主要介紹了Cocos2d-x 3.0中集成社交分享ShareSDK的詳細(xì)步驟和常見問題的解決方法以及需要注意的問題,需要的朋友可以參考下2014-04-04
Android實(shí)現(xiàn)果凍滑動(dòng)效果的控件
這篇文章給大家主要介紹了利用Android如何實(shí)現(xiàn)果凍效果滑動(dòng)效果的控件,實(shí)現(xiàn)的效果類似于iOS有阻尼效果的滑動(dòng)控件,一般我們比較親切地稱之為果凍控件,常見的如微信里[我]的那個(gè)面板模塊,即使沒有再多的選項(xiàng),也不會(huì)很生硬的不允許用戶滑動(dòng)。下面來一起看看吧。2016-11-11
RecyclerVIew實(shí)現(xiàn)懸浮吸頂效果
這篇文章主要為大家詳細(xì)介紹了RecyclerVIew實(shí)現(xiàn)懸浮吸頂效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09
Android CardView詳解及使用方法和實(shí)例
這篇文章主要介紹了Android CardView詳解及使用方法和實(shí)例的相關(guān)資料,這里附有實(shí)例代碼及實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-12-12
Android?獲取IP和UA實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了Android?獲取IP和UA實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android?進(jìn)入Activity時(shí)如何禁止彈出軟鍵盤輸入法
這篇文章主要介紹了Android?進(jìn)入Activity時(shí)如何禁止彈出軟鍵盤輸入法,文章圍繞主題展開具體內(nèi)容,需要的小伙伴可以參考一下2022-05-05
Android自定義控件實(shí)現(xiàn)球賽比分條效果
這篇文章主要為大家詳細(xì)介紹了Android自定義控件實(shí)現(xiàn)球賽比分條效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12
Flutter 枚舉值enum和int互相轉(zhuǎn)化總結(jié)
這篇文章主要為大家介紹了Flutter 枚舉值enum和int互相轉(zhuǎn)化總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02

