日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Retrofit2源码解析——网络调用流程(下)

發(fā)布時(shí)間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Retrofit2源码解析——网络调用流程(下) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Retrofit2源碼解析系列

  • Retrofit2源碼解析(一)
  • Retrofit2源碼解析——網(wǎng)絡(luò)調(diào)用流程(上)

本文基于Retrofit2的2.4.0版本

implementation 'com.squareup.retrofit2:retrofit:2.4.0' 復(fù)制代碼

上次我們分析到網(wǎng)絡(luò)請求是通過OkHttpCall類來完成的,下面我們就來分析下OkHttpCall類。

final class OkHttpCall<T> implements Call<T> {...@Overridepublic void enqueue(final Callback<T> callback) {checkNotNull(callback, "callback == null");okhttp3.Call call;Throwable failure;synchronized (this) {if (executed) throw new IllegalStateException("Already executed.");executed = true;call = rawCall;failure = creationFailure;if (call == null && failure == null) {try {//調(diào)用createRawCall創(chuàng)建OkHttp3的Callcall = rawCall = createRawCall();} catch (Throwable t) {throwIfFatal(t);failure = creationFailure = t;}}}...call.enqueue(new okhttp3.Callback() {@Overridepublic void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {Response<T> response;try {//解析返回的結(jié)果response = parseResponse(rawResponse);} catch (Throwable e) {callFailure(e);return;}try {callback.onResponse(OkHttpCall.this, response);} catch (Throwable t) {t.printStackTrace();}}@Overridepublic void onFailure(okhttp3.Call call, IOException e) {callFailure(e);}private void callFailure(Throwable e) {try {callback.onFailure(OkHttpCall.this, e);} catch (Throwable t) {t.printStackTrace();}}});}... } 復(fù)制代碼

OkHttpCall的enqueue方法主要干了2件事,一個(gè)是創(chuàng)建OkHttp3的Call用于執(zhí)行網(wǎng)絡(luò)請求;另一個(gè)是解析返回的結(jié)果并回調(diào)。下面我們來看看創(chuàng)建OkHttp3的Call的過程

//OkHttpCall.class private okhttp3.Call createRawCall() throws IOException {okhttp3.Call call = serviceMethod.toCall(args);if (call == null) {throw new NullPointerException("Call.Factory returned null.");}return call; } 復(fù)制代碼

可以發(fā)現(xiàn)是通過serviceMethod的toCall方法來創(chuàng)建的

//ServiceMethod.class okhttp3.Call toCall(@Nullable Object... args) throws IOException {RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,contentType, hasBody, isFormEncoded, isMultipart);...for (int p = 0; p < argumentCount; p++) {handlers[p].apply(requestBuilder, args[p]);}//最后調(diào)用OkHttpClient的newCall方法返回Callreturn callFactory.newCall(requestBuilder.build()); } 復(fù)制代碼

ServiceMethod的toCall方法也是通過OkHttpClient的newCall方法來返回Call的。

在我們通過OkHttpClient請求得到結(jié)果后,我們還需要將返回的結(jié)果Response解析成我們接口需要的實(shí)體類型,這就需要用到我們在創(chuàng)建Retrofit時(shí)設(shè)置的ConverterFactory了,比如GsonConverterFactory。

//OkHttpCall.class Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {ResponseBody rawBody = rawResponse.body();rawResponse = rawResponse.newBuilder().body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())).build();...ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);try {//通過serviceMethod的toResponse方法解析T body = serviceMethod.toResponse(catchingBody);return Response.success(body, rawResponse);} catch (RuntimeException e) {catchingBody.throwIfCaught();throw e;} } 復(fù)制代碼

OkHttpCall的parseResponse方法調(diào)用的是serviceMethod的toResponse方法來解析返回的結(jié)果。

//ServiceMethod.class R toResponse(ResponseBody body) throws IOException {return responseConverter.convert(body); } 復(fù)制代碼

在ServiceMethod中最后調(diào)用responseConverter的convert方法來轉(zhuǎn)換返回的結(jié)果。這個(gè)responseConverter和上面分析的CallAdapter的確定過程一樣,也是在ServiceMethod的build方法中,通過調(diào)用retrofit的requestBodyConverter方法遍歷我們傳入的ConverterFactory,直到找到合適的。

//Retrofit.class public <T> Converter<T, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {return nextRequestBodyConverter(null, type, parameterAnnotations, methodAnnotations); }public <T> Converter<T, RequestBody> nextRequestBodyConverter(@Nullable Converter.Factory skipPast, Type type, Annotation[] parameterAnnotations,Annotation[] methodAnnotations) {...int start = converterFactories.indexOf(skipPast) + 1;for (int i = start, count = converterFactories.size(); i < count; i++) {Converter.Factory factory = converterFactories.get(i);Converter<?, RequestBody> converter =factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);if (converter != null) {//noinspection uncheckedreturn (Converter<T, RequestBody>) converter;}}... } 復(fù)制代碼

需要注意的是在創(chuàng)建Retrofit時(shí)默認(rèn)添加了一個(gè)BuiltInConverters,這個(gè)是Retrofit為我們提供一個(gè)默認(rèn)的responseConverter,它主要處理的是返回類型是ResponseBody和Void的情況。

final class BuiltInConverters extends Converter.Factory {@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,Retrofit retrofit) {if (type == ResponseBody.class) {return Utils.isAnnotationPresent(annotations, Streaming.class)? StreamingResponseBodyConverter.INSTANCE: BufferingResponseBodyConverter.INSTANCE;}if (type == Void.class) {return VoidResponseBodyConverter.INSTANCE;}return null;}... } 復(fù)制代碼

因?yàn)槲覀円话惴祷刂殿愋投际蔷唧w的實(shí)體類型,所以我們需要添加自己的responseConverter,一般也就是GsonConverterFactory了。

至此,網(wǎng)絡(luò)調(diào)用的后半部分流程也清楚了:

我們調(diào)用Call對象的enqueue方法發(fā)起異步請求時(shí),實(shí)際上調(diào)用的是OkHttpCall對應(yīng)的enqueue方法。OkHttpCall會先調(diào)用ServiceMethod類的toCall方法利用OkHttpClient的newCall方法創(chuàng)建OkHttp3的call對象,然后利用這個(gè)call對象執(zhí)行具體的網(wǎng)絡(luò)請求。在網(wǎng)絡(luò)請求返回成功以后會調(diào)用ServiceMethod類的toResponse方法利用我們設(shè)置的responseConverter將返回結(jié)果轉(zhuǎn)換成我們需要的類型,然后通過我們設(shè)置的回調(diào)或是默認(rèn)的回調(diào)方法,將結(jié)果回調(diào)回主線程,從而完成整個(gè)請求過程。

總結(jié)

Retrofit2的網(wǎng)絡(luò)調(diào)用的整個(gè)流程我們已經(jīng)分析完了。通過這次分析,我們可以看到Retrofit2中最主要的就是3個(gè)類:Retrofit、ServiceMethod和OkHttpCall。這三個(gè)類指責(zé)明確,相互配合共同完成整個(gè)網(wǎng)絡(luò)調(diào)用的流程。

(1)Retrofit負(fù)責(zé)供外部初始化和定制,保存CallAdapter的列表和ResponseConverterFactory列表。

(2)ServiceMethod對應(yīng)每一個(gè)接口方法的信息,包括解析注解和參數(shù)等,同時(shí)它也是連接Retrofit和OkHttpCall的橋梁。ServiceMethod中保存著當(dāng)前接口對應(yīng)方法所需要的CallAdapter和ResponseConverter。利用CallAdapter將OkHttpCall轉(zhuǎn)換成接口需要的類型,供接口調(diào)用。利用toResponse方法讓OkHttpCall調(diào)用ResponseConverter解析網(wǎng)絡(luò)請求返回的結(jié)果。

(3)OkHttpCall則是用來執(zhí)行具體網(wǎng)絡(luò)請求。Retrofit2沒有直接使用OkHttp3的Call接口,而是有自己的Call接口。在OkHttpCall內(nèi)部通過組合的方法持有OkHttp3的Call接口,并通過ServiceMethod的toCall方法得到OkHttp3的call來進(jìn)行網(wǎng)絡(luò)請求,減少對OkHttp3的耦合。


歡迎關(guān)注我的微信公眾號,和我一起每天進(jìn)步一點(diǎn)點(diǎn)! 復(fù)制代碼

總結(jié)

以上是生活随笔為你收集整理的Retrofit2源码解析——网络调用流程(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。