摘要:此前在例子中調(diào)用的,就是設(shè)置返回的數(shù)據(jù)支持轉(zhuǎn)換為對(duì)象。最終會(huì)返回配置好的類。注釋處遍歷方法來對(duì)請(qǐng)求方式比如和請(qǐng)求地址進(jìn)行解析。的方法主要做的就是用來請(qǐng)求網(wǎng)絡(luò)并將返回的進(jìn)行數(shù)據(jù)轉(zhuǎn)換并回調(diào)給線程。至此,的源碼就講到這里。
前言
最近文章的產(chǎn)出確實(shí)很少,因?yàn)槲艺趯懸槐続ndroid進(jìn)階書籍,兩頭很難兼顧,但是每個(gè)月也得至少發(fā)一篇博客。上一篇我們介紹了Retrofit的使用方法,這一篇我們照例來學(xué)習(xí)Retrofit的源碼。
當(dāng)我們使用Retrofit請(qǐng)求網(wǎng)絡(luò)時(shí),首先要寫請(qǐng)求接口:
public interface IpService { @GET("getIpInfo.php?ip=59.108.54.37") CallgetIpMsg();
接著我們通過調(diào)用如下代碼來創(chuàng)建Retrofit:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build();
Retrofit 是通過建造者模式構(gòu)建出來的,接下來查看Builder方法做了什么:
public Builder() { this(Platform.get()); }
很簡(jiǎn)短,查看Platform的get方法,如下所示。
private static final Platform PLATFORM = findPlatform(); static Platform get() { return PLATFORM; } private static Platform findPlatform() { try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { return new Android(); } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } try { Class.forName("org.robovm.apple.foundation.NSObject"); return new IOS(); } catch (ClassNotFoundException ignored) { } return new Platform(); }
Platform的get方法最終調(diào)用的是findPlatform方法,根據(jù)不同的運(yùn)行平臺(tái)來提供不同的線程池。接下來查看build方法,代碼如下所示。
public Retrofit build() { if (baseUrl == null) {//1 throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory;//2 if (callFactory == null) { callFactory = new OkHttpClient();//3 } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor();//4 } ListadapterFactories = new ArrayList<>(this.adapterFactories);//5 adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); List converterFactories = new ArrayList<>(this.converterFactories);//6 return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }
從注釋1處可以看出baseUrl 是必須指定的。注釋2處callFactory默認(rèn)為this.callFactory,this.callFactory就是我們?cè)跇?gòu)建Retrofit時(shí)調(diào)用callFactory方法所傳進(jìn)來的,如下所示。
public Builder callFactory(okhttp3.Call.Factory factory) { this.callFactory = checkNotNull(factory, "factory == null"); return this; }
因此,如果需要對(duì)OkHttpClient進(jìn)行設(shè)置,則可以構(gòu)建OkHttpClient對(duì)象,然后調(diào)用callFactory方法將設(shè)置好的OkHttpClient傳進(jìn)去。注釋3處,如果沒有設(shè)置callFactory則直接創(chuàng)建OkHttpClient。注釋4的callbackExecutor用來將回調(diào)傳遞到UI線程。注釋5的adapterFactories主要用于存儲(chǔ)對(duì)Call進(jìn)行轉(zhuǎn)化的對(duì)象,后面在Call的創(chuàng)建過程會(huì)再次提到它。注釋6處的converterFactories主要用于存儲(chǔ)轉(zhuǎn)化數(shù)據(jù)對(duì)象,后面也會(huì)提及到。此前在例子中調(diào)用的addConverterFactory(GsonConverterFactory.create()),就是設(shè)置返回的數(shù)據(jù)支持轉(zhuǎn)換為Gson對(duì)象。最終會(huì)返回配置好的Retrofit類。
2.Call的創(chuàng)建過程緊接著我們創(chuàng)建Retrofit實(shí)例并調(diào)用如下代碼來生成接口的動(dòng)態(tài)代理對(duì)象:
IpService ipService = retrofit.create(IpService.class);
接下來看Retrofit的create方法做了什么,代碼如下所示。
publicT create(final Class service) { Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(service); } return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, Object... args) throws Throwable { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } ServiceMethod serviceMethod = loadServiceMethod(method);//1 OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
可以看到create方法返回了一個(gè)Proxy.newProxyInstance動(dòng)態(tài)代理對(duì)象,當(dāng)我們調(diào)用IpService的getIpMsg方法最終會(huì)調(diào)用InvocationHandler的invoke 方法,它有3個(gè)參數(shù),第一個(gè)是代理對(duì)象,第二個(gè)是調(diào)用的方法,第三個(gè)是方法的參數(shù)。注釋1處的loadServiceMethod(method)中的method就是我們定義的getIpMsg方法。接下來查看loadServiceMethod方法里做了什么:
private final MapserviceMethodCache = new LinkedHashMap<>(); ServiceMethod loadServiceMethod(Method method) { ServiceMethod result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder(this, method).build(); serviceMethodCache.put(method, result); } } return result; }
首先會(huì)從serviceMethodCache查詢傳入的方法是否有緩存,如果有就用緩存的ServiceMethod,如果沒有就創(chuàng)建一個(gè),并加入serviceMethodCache緩存起來。接下來看ServiceMethod是如何構(gòu)建的,代碼如下所示。
public ServiceMethod build() { callAdapter = createCallAdapter();//1 responseType = callAdapter.responseType();//2 if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError(""" + Utils.getRawType(responseType).getName() + "" is not a valid response body type. Did you mean ResponseBody?"); } responseConverter = createResponseConverter();//3 for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation);//4 } ... int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler>[parameterCount]; for (int p = 0; p < parameterCount; p++) { Type parameterType = parameterTypes[p]; if (Utils.hasUnresolvableType(parameterType)) { throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s", parameterType); } Annotation[] parameterAnnotations = parameterAnnotationsArray[p];//5 if (parameterAnnotations == null) { throw parameterError(p, "No Retrofit annotation found."); } parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations); } ... return new ServiceMethod<>(this); }
注釋1處調(diào)用了createCallAdapter方法,它最終會(huì)得到我們?cè)跇?gòu)建Retrofit調(diào)用build方法時(shí)adapterFactories添加的對(duì)象的get方法,Retrofit的build方法部分代碼:
ListadapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
adapterFactories列表默認(rèn)會(huì)添加defaultCallAdapterFactory,defaultCallAdapterFactory指的是ExecutorCallAdapterFactory,ExecutorCallAdapterFactory的get方法如下所示。
public CallAdapter> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter >() { @Override public Type responseType() { return responseType; } @Override public Call adapt(Call call) { return new ExecutorCallbackCall<>(callbackExecutor, call); } }; }
get方法會(huì)得到CallAdapter對(duì)象,它的responseType方法會(huì)返回?cái)?shù)據(jù)的真實(shí)類型,比如 Call
接著回到ServiceMethod的 build方法,注釋2處調(diào)用CallAdapter的responseType得到的是返回?cái)?shù)據(jù)的真實(shí)類型。
注釋3處調(diào)用createResponseConverter方法來遍歷converterFactories列表中存儲(chǔ)的Converter.Factory,并返回一個(gè)合適的Converter用來轉(zhuǎn)換對(duì)象。此前我們?cè)跇?gòu)建Retrofit 調(diào)用了addConverterFactory(GsonConverterFactory.create())將GsonConverterFactory(Converter.Factory的子類)添加到converterFactories列表中,表示返回的數(shù)據(jù)支持轉(zhuǎn)換為Json對(duì)象。
注釋4處遍歷parseMethodAnnotation方法來對(duì)請(qǐng)求方式(比如GET、POST)和請(qǐng)求地址進(jìn)行解析。注釋5處對(duì)方法中的參數(shù)注解進(jìn)行解析(比如@Query、@Part)。最后創(chuàng)建ServiceMethod類并返回。
接下來回過頭來查看Retrofit的create方法,在調(diào)用了loadServiceMethod方法后會(huì)創(chuàng)建OkHttpCall,OkHttpCall的構(gòu)造函數(shù)只是進(jìn)行了賦值操作。緊接著調(diào)用serviceMethod.callAdapter.adapt(okHttpCall),callAdapter的adapt方法前面講過,它會(huì)創(chuàng)建ExecutorCallbackCall,ExecutorCallbackCall的部分代碼如下所示。
ExecutorCallbackCall(Executor callbackExecutor, Calldelegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback callback) { if (callback == null) throw new NullPointerException("callback == null"); delegate.enqueue(new Callback () {//1 @Override public void onResponse(Call call, final Response response) { callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled")); } else { callback.onResponse(ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); }
可以看出ExecutorCallbackCall是對(duì)Call的封裝,它主要添加了通過callbackExecutor將請(qǐng)求回調(diào)到UI線程。
當(dāng)我們得到Call對(duì)象后會(huì)調(diào)用它的enqueue方法,其實(shí)調(diào)用的是ExecutorCallbackCall的enqueue方法,而從注釋1處可以看出ExecutorCallbackCall的enqueue方法最終調(diào)用的是delegate的enqueue方法。delegate從Retrofit的create方法的代碼中我們知道它其實(shí)就是OkHttpCall。
接下來我們就來查看OkHttpCall的enqueue方法,代碼如下所示。
public void enqueue(final Callbackcallback) { if (callback == null) throw new NullPointerException("callback == null"); okhttp3.Call call; ... call.enqueue(new okhttp3.Callback() {//1 @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException { Response response; try { response = parseResponse(rawResponse);//2 } catch (Throwable e) { callFailure(e); return; } callSuccess(response); } ... }
注釋1處調(diào)用了okhttp3.Call的enqueue方法。注釋2處調(diào)用parseResponse方法:
ResponseparseResponse(okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); ... int code = rawResponse.code(); if (code < 200 || code >= 300) { try { ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } } if (code == 204 || code == 205) { return Response.success(null, rawResponse); } ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { T body = serviceMethod.toResponse(catchingBody);//2 return Response.success(body, rawResponse); } catch (RuntimeException e) { catchingBody.throwIfCaught(); throw e; } }
根據(jù)返回的不同的狀態(tài)碼code值來做不同的操作,如果順利則會(huì)調(diào)用注釋2處的代碼,接下來看toResponse方法里做了什么:
T toResponse(ResponseBody body) throws IOException { return responseConverter.convert(body); }
這個(gè)responseConverter就是此前講過在ServiceMethod的build方法調(diào)用createResponseConverter方法返回的Converter,在此前的例子中我們傳入的是GsonConverterFactory,因此可以查看GsonConverterFactory的代碼,如下所示。
public final class GsonConverterFactory extends Converter.Factory { ... @Override public ConverterresponseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonResponseBodyConverter<>(gson, adapter); } ... }
在GsonConverterFactory 中有一個(gè)方法responseBodyConverter,它最終會(huì)創(chuàng)建GsonResponseBodyConverter:
final class GsonResponseBodyConverterimplements Converter { private final Gson gson; private final TypeAdapter adapter; GsonResponseBodyConverter(Gson gson, TypeAdapter adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { return adapter.read(jsonReader); } finally { value.close(); } } }
在GsonResponseBodyConverter的convert方法里會(huì)將回調(diào)的數(shù)據(jù)轉(zhuǎn)換為Json格式。因此我們也知道了此前調(diào)用responseConverter.convert是為了轉(zhuǎn)換為特定的數(shù)據(jù)格式。
Call的enqueue方法主要做的就是用OKHttp來請(qǐng)求網(wǎng)絡(luò)并將返回的Response進(jìn)行數(shù)據(jù)轉(zhuǎn)換并回調(diào)給UI線程。
至此,Retrofit的源碼就講到這里。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/70583.html
摘要:音樂團(tuán)隊(duì)分享數(shù)據(jù)綁定運(yùn)行機(jī)制分析一個(gè)項(xiàng)目搞定所有主流架構(gòu)單元測(cè)試一個(gè)項(xiàng)目搞定所有主流架構(gòu)系列的第二個(gè)項(xiàng)目。代碼開源,展示了的用法,以及如何使用進(jìn)行測(cè)試,還有用框架對(duì)的進(jìn)行單元測(cè)試。 Android 常用三方框架的學(xué)習(xí) Android 常用三方框架的學(xué)習(xí) likfe/eventbus3-intellij-plugin AS 最新可用 eventbus3 插件,歡迎品嘗 簡(jiǎn)單的 MVP 模...
摘要:看下圖所示,摘自網(wǎng)絡(luò)的創(chuàng)建流程源碼分析實(shí)例是使用建造者模式通過類進(jìn)行創(chuàng)建的。創(chuàng)建了一個(gè)含有對(duì)象實(shí)例的,并返回給源碼分析添加一個(gè)調(diào)用適配器工廠,用于支持服務(wù)方法返回類型注意生產(chǎn)的是,那么又是什么呢可以看到源代碼如下所示,它是一個(gè)接口。 目錄介紹 1.首先回顧Retrofit簡(jiǎn)單使用方法 2.Retrofit的創(chuàng)建流程源碼分析 2.1 Retrofit對(duì)象調(diào)用Builder()源碼解...
閱讀 3100·2021-02-22 17:12
閱讀 722·2019-08-30 15:55
閱讀 3096·2019-08-30 15:54
閱讀 1392·2019-08-29 16:56
閱讀 1866·2019-08-29 15:13
閱讀 1723·2019-08-29 13:19
閱讀 605·2019-08-26 13:40
閱讀 2828·2019-08-26 10:26