Retorfit源碼學習
一.什么是Retorfit
- 簡單的來說Retorfit是封裝到Okhttp的一個網(wǎng)絡請求庫,方便客戶端調用去請求,返回的數(shù)據(jù)方便客戶端解析,支持Rxjava鏈式調用,內部通過動態(tài)代理+自定義注解方式去獲取客戶端定義的方法和方法中定義的注解,參數(shù)等,交給Okhttp請求,拿到結果通過數(shù)據(jù)轉換工廠去轉換,通過Rxjava->Observable去發(fā)射真正的網(wǎng)絡請求也就是Okhttp,客戶端拿到發(fā)射的事件流做相應的操作即可。那么在源碼分析之前先來看看在使用GsonConverterFactory和RxJavaCallAdapterFactory時,請求的例子。
二.請求實例
1.創(chuàng)建retorfit實例
private HttpClient() {
client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LogInterceptor())
.build();
retrofit = new Retrofit.Builder()
.baseUrl(Constants.SERVER_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
apiService = retrofit.create(MedexApiService.class);
}
- 可以看到Retorfit創(chuàng)建時是通過Builder模式去構建實例的,何為Builder模式,簡單說明下Builder模式可以將一個類的構建和表示進行分離。說白了,也就是減少對象創(chuàng)建過程中引入的多個構造函數(shù)、可選參數(shù)以及多個 set方法 過度使用導致的不必要的復雜性。
2.定義接口
public interface MedexApiService {
@FormUrlEncoded
@POST("./")
Observable<BaseResponse<Logindata>> login(@FieldMap Map<String, String> params);
}
3.客戶端調用
...此處省略代碼
HttpClient.getInstance().
getMedexApiService().
login(ParamsTool.getParms(params))
...此處省略代碼
一次請求就這么完美的執(zhí)行了,配合rxjava簡直爽的不要不要的。那么它內部是如何處理傳遞的參數(shù),和拿到參數(shù)后如何去請求,拿到結果后如何轉換為客戶端定義的類型,轉換類型后又如何包裝成rxjava Observable的,帶著一些列問題,我們去探探究竟。
三.源碼分析
從上面例子已經看出創(chuàng)建Retorfit實例時,通過Builder設置一些參數(shù),那么這些參數(shù)用來干什么的,有什么用,它內部又如何設置這些值。帶著疑問我們來看看new Builder和Builder中設置的這些參數(shù)用來干什么。
1.builder初始化及一些set方法
- newBuilder
public Builder() {
//調用Platform.get()
this(Platform.get());
}
//Platform.class
private static final Platform PLATFORM = findPlatform();
//get方法調用findPlatform返回一個Platform
static Platform get() {
return PLATFORM;
}
//可以看到findPlatform方法根據(jù)不同平臺返回不同的Platform,那我們直接來看
//new Android()這塊
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();
}
//Android繼承自Platform
static class Android extends Platform {
//可以當作是用來線程切換的執(zhí)行器
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//默認的網(wǎng)絡發(fā)射器,RxJavaCallAdapterFactory就是CallAdapter.Factory的具體工廠,如果外部不提供就用這個默認的,具體ExecutorCallAdapterFactory源碼這里不做分析,只分析RxJavaCallAdapterFactory。
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
//回調方法執(zhí)行器,作用是用來線程切換的。
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
//在Retorfit中默認是將okhttp請求的返回的數(shù)據(jù)切換到主線程中
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
//最終調用Builder的第二個構造方法,并且添加默認的數(shù)據(jù)轉換器
Builder(Platform platform) {
this.platform = platform;
converterFactories.add(new BuiltInConverters());
}
- baseUrl()
public Builder baseUrl(String baseUrl) {
//檢測url合法性
checkNotNull(baseUrl, "baseUrl == null");
//外部傳進來的String url 轉換為Okhttp中認可的HttpUrl
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
//得到url的分片
List<String> pathSegments = baseUrl.pathSegments();
//判斷是否以/結尾 不是就拋出異常
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
- client()
//設置okhttpClient
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
//檢查合法性并賦值給 Budiler中 callFactory
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
- addConverterFactory()
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
- 設置轉換器,可以看到參數(shù)需要一個轉換工廠,Converter.Factory,我們傳進來的是一個GsonConverterFactory具體的工廠,這里Retorfit用到的是工廠方法設計模式,那先來看看Converter.Factory 定義的工廠方法都有哪些。
關于工廠設計模式請參考此文章
//將HTTP響應主體轉換為? 也就是我們代碼中定義的類型
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
//將代碼中請求的類型轉換為HTTP請求體
//主要用于對Part、PartMap、Body注解的處理
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
// 這里用于對Field、FieldMap、Header、Path、Query、QueryMap注解的理
// Retrfofit對于上面的幾個注解默認使用的是調用toString方法
public Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
- 以上三個方法都是解析收據(jù)時用到的,具體實現(xiàn)在創(chuàng)建Retorfit時傳入的GsonConverterFactory中,可自行查閱Gosn解析的一些api。
addCallAdapterFactory()
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
- 將RxJavaCallAdapterFactory實例添加到adapterFactories集合中,和添加解析器一樣,也是一個工廠方法設計模式,那我們看看CallAdapter.Factory中定義的重要方法
//根據(jù)方法返回類型和方法上定義的注解返回CallAdapter,具體的CallAdapter在RxJavaCallAdapterFactory 中內部類SimpleCallAdapter實現(xiàn),這里只針對,定義接口中返回Observable<BaseResponse>來說明
public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,Retrofit retrofit);
最后我們來看下build完成構建后的代碼
public Retrofit build() {
//檢查是否設置了baseUrl
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
//檢查是否設置了OkhttpClient,如果沒有new一個
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//回調方法執(zhí)行器是否為null,如果我們沒調用set設置那么默認為null
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
//生成默認的回調方法執(zhí)行器,默認的回調方法執(zhí)行器就是 //MainThreadExecutor
callbackExecutor = platform.defaultCallbackExecutor();
}
//講adapterFactories集合中添加的數(shù)據(jù)復制到新的集合中,adapterFactories添加是我們外部傳進來的RxJavaCallAdapterFactory
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//在新的集合中又添加一個默認的網(wǎng)絡發(fā)射器具體請查看Android中的defaultCallAdapterFactory方法,那么網(wǎng)絡發(fā)射器集合中目前有兩個。第一個是 RxJavaCallAdapterFactory。第二個是默認的網(wǎng)絡發(fā)射器。
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
//上文中已經說明在Builder有參構造中已添加了一個默認的數(shù)據(jù)轉換器,那么我們在外部又添加了一個GsonConverterFactory,那么這個轉換器集合中有兩個。第一個是默認的轉換器,第二個是外部提供的GsonConverterFactory
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
//構造Retrofit實例,并且把Builder中設置的參數(shù)傳遞給Retrofit
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
- 上面我們分析了創(chuàng)建Retorfit時都干了什么,大致總結一下,當newBuilder時,創(chuàng)建默認的數(shù)據(jù)轉換器。調用Builder一系列set方法設置GsonConverterFactory數(shù)據(jù)轉換器,設置RxjavaCallAdapter網(wǎng)絡發(fā)射器,設置OkHttpClient,構造Builder時,把設置的兩個工廠(GsonConverterFactory轉換器和RxjavaCallAdapter網(wǎng)絡發(fā)射器)加入到各自集合中,那么此時兩個集合中各自的數(shù)量都是兩個,一個是默認的,一個是外部我們自己傳遞進來的,把這些參數(shù)通過Retorfit構造方法并傳遞個Retorfit。
上面我們大致說了下設置數(shù)據(jù)轉換器(GsonConverterFactory)和設置網(wǎng)絡發(fā)射器(RxjavaCallAdapter),以及默認的數(shù)據(jù)轉換器(BuiltInConverters)和網(wǎng)絡發(fā)射器(ExecutorCallAdapterFactory),那么接下來,講分析Retorfit中的create方法了。
2.Retorfit的create方法都干了什么。
public <T> T create(final Class<T> service) {
//驗證是否是接口
Utils.validateServiceInterface(service);
//是否提前預加載接口中的所有方法,并且緩存??梢酝ㄟ^Builder去set設置
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//創(chuàng)建代理類
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
private final Platform platform = Platform.get();
//這個 invoke方法是在代理類調用最終對象的方法時,會調用此方法。
//proxy 是代理對象,method是被代理方法,args 被代理參數(shù)
@Override
public Object invoke(Object proxy, Method method, Object... args) throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//默認值是false先不管(Platform類中是false,默認的Android繼承于Platform,但是并沒有去重寫此方法,所以該方法返回false)
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//重點 1
//解析method中的注解,得到注解中的參數(shù)。
//初始化數(shù)據(jù)解析器,初始化網(wǎng)絡發(fā)射器
//ServiceMethod 可以說是封裝了請求的所有參數(shù)。
ServiceMethod serviceMethod = loadServiceMethod(method);
//重點2 構建Okhttp請求,真正去請求網(wǎng)絡的執(zhí)行器。
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//重點3 包裝網(wǎng)絡請求執(zhí)行器交給網(wǎng)絡發(fā)射器來操作。
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
從以上分析可知到,當調用Retorfit中的create方法時,創(chuàng)建代理類,當調用接口中定義的方法時,其實就會調用代理類的 invoke 方法,在此方法中,Retorfit攔截并做了三件事。
- 解析代理方法中的method 注解 ,包括method上的注解和method參數(shù)注解,并做了相應的緩存,創(chuàng)建外部設置進來的數(shù)據(jù)解析器GsonConverterFactory.create(),和網(wǎng)絡發(fā)射器RxJavaCallAdapterFactory.create()。
- 創(chuàng)建OkhttpCall 這個類是真正去執(zhí)行網(wǎng)絡操作的類。并且把封裝好的解析器GsonConverterFactory.create(),和發(fā)射器RxJavaCallAdapterFactory.create()的ServiceMethod 和方法中的參數(shù)傳遞給它。
- 將創(chuàng)建的okhttpCall對象交給網(wǎng)絡發(fā)射器來發(fā)射也就是我們在創(chuàng)建Retorfit時傳進來的RxJavaCallAdapterFactory.create()
那么接下來對上文標注的重點一一分析。
3.ServiceMethod 都干了什么。
ServiceMethod serviceMethod = loadServiceMethod(method);
當調用loadServiceMethod 時,傳遞的是我們接口中定義的方法。LoadServiceMethod方法代碼如下:
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
//先在緩存中找,key是接口中定義的method,值是ServiceMethod
result = serviceMethodCache.get(method);
if (result == null) {
//如果沒找到,那么就去構建一個,并且緩存
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
- 此方法說明了,在調用retorfit.create方法時,為什么我們有時會創(chuàng)建一個單例的實例,代理對象是單例的,那么足可以說該實例中的方法也是唯一的,所以,在這一步起到緩存的作用。
3.1 ServiceMethod.Builder(this, method)
將Retofit實例以及被代理方法傳遞給ServiceMethod中的Builder.
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//獲取method上定義的注解
this.methodAnnotations = method.getAnnotations();
//獲取method中參數(shù)類型
this.parameterTypes = method.getGenericParameterTypes();
//獲取method中參數(shù)注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
再看.build()方法
public ServiceMethod build() {
//重點1.1 創(chuàng)建網(wǎng)絡發(fā)射器
callAdapter = createCallAdapter();
//返回類型
responseType = callAdapter.responseType();
...省略一些判斷代碼
//重點1.2創(chuàng)建相應的數(shù)據(jù)轉換器
responseConverter = createResponseConverter();
//遍歷method上的的注解并解析
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
...省略一些判斷
//得到方法注解參數(shù)長度
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
//遍歷方法注解參數(shù)并解析封裝在parameterHandlers數(shù)組中
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
...省略代碼
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
...省略代碼
//返回ServiceMethod實例
return new ServiceMethod<>(this);
}
針對上面創(chuàng)建ServiceMethod時,標注的重點看下
3.1.1 創(chuàng)建網(wǎng)絡發(fā)射器
private CallAdapter<?> createCallAdapter() {
//獲取method返回值類型
Type returnType = method.getGenericReturnType();
...省略判斷
//獲取method上的注解
Annotation[] annotations = method.getAnnotations();
try {
//調用retrofit中的callAdapter
return retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) {
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
接著看retrofit.callAdapter方法
//內部調用nextCallAdapter方法
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
...省略判斷
//傳入的skipPast是null那么adapterFactories.indexOf(skipPast)得到的是-1,
//那么start就是0,也就是從0開始遍歷我們剛開始在Builder構建出的網(wǎng)絡發(fā)射器集合,
//并且調用這個網(wǎng)絡發(fā)射器集合的get方法把返回類型,和方法上的注解還有Retorfit傳遞過去。并且返回CallAdapter<?>接口。
//由于RxJavaCallAdapterFactory實現(xiàn)了CallAdapter接口,
//上文中也提到,通過Retorfit.Builder傳遞進來的RxjavaCallAdapter在集合的第一個,
//所以我們著重看下,RxjavaCallAdapter.get()方法實現(xiàn)。
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...省略代碼
}
//RxjavaCallAdapter.java
@Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
String canonicalName = rawType.getCanonicalName();
boolean isSingle = "rx.Single".equals(canonicalName);
boolean isCompletable = "rx.Completable".equals(canonicalName);
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
..省略一些判斷方法,
//因為這里我們只分析返回接口中定義的返回Observable
CallAdapter<Observable<?>> callAdapter = getCallAdapter(returnType, scheduler);
return callAdapter;
}
//可以看到調用了getCallAdapter()方法,繼續(xù)看getCallAdapter()方法
private CallAdapter<Observable<?>> getCallAdapter(Type returnType, Scheduler scheduler) {
//根據(jù)返回的泛型type得到Observable中定義的泛型參數(shù)type
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
//根據(jù)泛型參數(shù)type得到參數(shù)Class
Class<?> rawObservableType = getRawType(observableType);
//Observable中的泛型是否是Response
if (rawObservableType == Response.class) {
...省略驗證代碼
Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
return new ResponseCallAdapter(responseType, scheduler);
}
//Observable中的泛型是否是Result
if (rawObservableType == Result.class) {
...省略驗證代碼
Type responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
return new ResultCallAdapter(responseType, scheduler);
}
//由于我們給的例子是Observable中的泛型參數(shù)是我們自己定義的對象,
//那么最終返回SimpleCallAdapter
return new SimpleCallAdapter(observableType, scheduler);
}
至此我們上文中標注的1.1重點已分析完,大致總結下:在ServiceMethod調用Builder時,調用了createCallAdapter,而createCallAdapter又調用了Retorfit中的callAdapter方法,callAdapter內部調用nextCallAdapter方法,再在nextCallAdapter方法中,遍歷我之前在Retorfit構建的網(wǎng)絡發(fā)射器集合,并調用其內部元素的get方法,由于我們設置的RxJavaCallAdapterFactory在集合的首位,所以,我們直接看RxJavaCallAdapterFactory的get方法,根據(jù)我們在代碼中定義的返回值(Observable)以及返回值泛型(BaseResponse)最中調用了并返回了SimpleCallAdapter。那么至此,網(wǎng)絡發(fā)射器具體的實現(xiàn)已找到,接著分析重點2.2。
3.1.2
private Converter<ResponseBody, T> createResponseConverter() {
//獲取方法上的
Annotation[] annotations = method.getAnnotations();
//返回retrofit中responseBodyConverter方法并把接口返回類型和方法上的注解傳遞給它
return retrofit.responseBodyConverter(responseType, annotations);
...省略異常代碼
}
//Retorfit.java
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
//最終調用 nextResponseBodyConverter方法
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
Type type, Annotation[] annotations) {
...省略合法性代碼
//因為skipPast傳遞的是null,那么start也是從0開始,
//那么集合中第一個元素的BuiltInConverters,而BuiltInConverters實現(xiàn)了responseBodyConverter,由于其內部根據(jù)判斷沒有我們想要的返回類型,
//所以最終返回null。接著遍歷第二個元素,也就是我們外部設置進來的GsonConverterFactory中的responseBodyConverter方法,
//最終返回GsonResponseBodyConverter這個對象。
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
return (Converter<ResponseBody, T>) converter;
}
}
...省略異常代碼
}
- 總結一下,當創(chuàng)建響應數(shù)據(jù)轉換時,遍歷數(shù)據(jù)轉換集合,判斷,驗證我們的返回類型,由于默認的相應數(shù)據(jù)轉換器(BuiltInConverters),在responseBodyConverter方法中沒有我們想要的返回類型,所以最終返回null,那么在遍歷第二個元素時,也就是外部提供的GsonConverterFactory,其內部responseBodyConverter方法返回GsonResponseBodyConverter 這個類對象,所以,得到一條結論,在我們上述定義的請求例子中,當網(wǎng)絡請求完畢后,數(shù)據(jù)轉換在GsonResponseBodyConverter中操作的。
至此,構建ServiceMethod源碼已分析完。根據(jù)上面分析ServiceMethod構建時,完成了網(wǎng)絡發(fā)射器的創(chuàng)建和響應數(shù)據(jù)轉換器的創(chuàng)建,以及方法上方法參數(shù)中的注解解析。所以,ServiceMethod是封裝了網(wǎng)絡請求的所有參數(shù)以及網(wǎng)絡請求數(shù)據(jù)的轉換和網(wǎng)絡請求發(fā)射器。
4.創(chuàng)建OkHttpCall
//把封裝好的所有網(wǎng)絡請求相關的數(shù)據(jù)轉換器和網(wǎng)絡發(fā)射器傳遞給OkHttpCall,以及方法中定義的參數(shù)。
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//接著看OkhttpCall類中關鍵方法
@Override
public synchronized Request request() {
okhttp3.Call call = rawCall;
//默認為null
if (call != null) {
return call.request();
}
try {
//創(chuàng)建okhttpCall對象并調用okhttp的request方法
return (rawCall = createRawCall()).request();
} catch (RuntimeException e) {
creationFailure = e;
throw e;
} catch (IOException e) {
creationFailure = e;
throw new RuntimeException("Unable to create request.", e);
}
}
//創(chuàng)建okhttp3.Call
private okhttp3.Call createRawCall() throws IOException {
//內部通過ServiceMethod類中的方法構建一個Request
Request request = serviceMethod.toRequest(args);
//調用我們通過Retorfit Buidler傳遞進來的OkhttClient對象的newCall方法,創(chuàng)建okhttp3.Call
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
//就著看真正去請求的操作(這里我們只說同步請求)
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
...省略判斷
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
//解析數(shù)據(jù),拿到結果后最終會調用GsonResponseBodyConverter中的convert方法進行數(shù)據(jù)轉換。
return parseResponse(call.execute());
}
至此OkhttpCall中請求和相應的代碼已分析完。解析來看最后一步,也就是網(wǎng)絡發(fā)射器代碼。
5.網(wǎng)絡發(fā)射器
上文中標注的重點3代碼如下
serviceMethod.callAdapter.adapt(okHttpCall)
上面我們分析了ServiceMethod構建源碼,所以我們知道這個callAdapter就是SimpleCallAdapter,那么直接看SimpleCallAdapter中的adapt方法源碼。
@Override
public <R> Observable<R> adapt(Call<R> call) {
//創(chuàng)建Observable并發(fā)射CallOnSubscribe中的事件。
Observable<R> observable = Observable.create(new CallOnSubscribe<>(call)) //
.flatMap(new Func1<Response<R>, Observable<R>>() {
@Override
public Observable<R> call(Response<R> response) {
if (response.isSuccessful()) {
return Observable.just(response.body());
}
return Observable.error(new HttpException(response));
}
});
//默認為null
if (scheduler != null) {
return observable.subscribeOn(scheduler);
}
return observable;
}
}
//看看CallOnSubscribe中的實現(xiàn)
static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> {
private final Call<T> originalCall;
//得到OkhttpCall的引用
CallOnSubscribe(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override public void call(final Subscriber<? super Response<T>> subscriber) {
final Call<T> call = originalCall.clone();
//把OkhttpCall加入到subscriptions集合中用于下面判斷是否取消訂閱
//ubscriber.isUnsubscribed(),其實就是是否取消網(wǎng)絡請求。
//當客戶端調用ubscriber.unsubscribed時,其實調用了call.cancel();
subscriber.add(Subscriptions.create(new Action0() {
@Override public void call() {
call.cancel();
}
}));
try {
//開始同步執(zhí)行,所以如果接口中定義的是Observable返回的話,那么就會執(zhí)行同步請求,
//所以我們在代碼中往往會寫指定在子線程中發(fā)射事件,在主線程中消費時間,因為是同步請求嘛。
Response<T> response = call.execute();
if (!subscriber.isUnsubscribed()) {
//調用onNext
subscriber.onNext(response);
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
//出現(xiàn)異常,那么調用onError
if (!subscriber.isUnsubscribed()) {
subscriber.onError(t);
}
return;
}
//最終調用onCompleted
if (!subscriber.isUnsubscribed()) {
subscriber.onCompleted();
}
}
}
至此,Retorfit源碼中主要流程分析完畢,關鍵分析點上面已標出,其他代碼還是根據(jù)實際情況來分析,如果客戶端沒有用到rxjava+Retorfit,用Retorfit自帶的Call,那么分析流程就不一樣了,或者用到其他數(shù)據(jù)轉換器,亦或者,接口中定義的不是Observable,而是Completable或者Single。