序言
做Android開發(fā)的小伙伴都知道,現(xiàn)在最流行的網(wǎng)絡(luò)框架就是RxJava+Retrofi+OkHttp。今天我們就一起來學(xué)習(xí)一下Retrofit內(nèi)部如何實(shí)現(xiàn)。
一.如何使用Retrofit
- 在工程Module的build.gradle中添加Retrofit依賴庫(kù):
api "com.squareup.retrofit2:retrofit:2.0.0"
api "com.squareup.retrofit2:adapter-rxjava:2.0.0"
api "com.squareup.retrofit2:converter-jackson:2.0.0"
- 定義一個(gè)提供服務(wù)的接口Service:
public interface APIService {
@GET("hello/world")
Observable<Response<String>> getNews(@Query("num") String num, @Query("page")String page);
}
- 使用
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://apis.baidu.com/txapi/")
.addConverterFactory(JacksonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
APIService service = retrofit.create(APIService.class);
service.getNews("10","1")
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.subscribe(new Action1<Response<String>>() {
@Override
public void call(Response<String> response) {
}
});
到這里就已經(jīng)返回了一個(gè)經(jīng)過基礎(chǔ)轉(zhuǎn)換的Observable,之后我們只需要對(duì)這個(gè)Observable進(jìn)行處理,得到我們想要的數(shù)據(jù)即可。
二.Retrofit源碼解析
可以說整個(gè)使用過程并不復(fù)雜,在我們用這么少的代碼就能夠發(fā)送一個(gè)網(wǎng)絡(luò)請(qǐng)求的背后,是Retrofit幫我們做了大量的工作,包括解析參數(shù),組裝請(qǐng)求,對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換和適配...
下面我們通過源碼來分析Retrofit:
1. 構(gòu)建Retrofit對(duì)象
Retrofit是通過Builder模式來構(gòu)建對(duì)象,我們先看一下Retrofit的定義:
public final class Retrofit {
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
private final okhttp3.Call.Factory callFactory;
private final HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories;
private final List<CallAdapter.Factory> adapterFactories;
private final Executor callbackExecutor;
private final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
//省略其他代碼
}
Retrofit包含一些重要的成員:
- serviceMethodCache:是一個(gè)LinkedHashMap<Method, ServiceMethod>,聲明時(shí)直接初始化,用來緩存ServiceMethod,避免重復(fù)創(chuàng)建,可以提高性能
- callFactory:請(qǐng)求工廠,主要要來創(chuàng)建請(qǐng)求(Call),可以理解為OkHttpClient
- baseUrl:服務(wù)器域名,即服務(wù)器host
- converterFactories:數(shù)據(jù)解析工廠,可以創(chuàng)建Converter,主要用來解析Response,可以有多個(gè),但只有一個(gè)會(huì)進(jìn)行真正的解析操作
- adapterFactories:數(shù)據(jù)適配工廠,可以創(chuàng)建適配器,主要作用是把Response中的數(shù)據(jù)轉(zhuǎn)換為某種數(shù)據(jù)源類型,比如我們示例中把Response轉(zhuǎn)換為rxjava.Observable
- callbackExecutor:請(qǐng)求回調(diào)
- validateEagerly:是否設(shè)置為饑餓模式,如果設(shè)置為饑餓模式,會(huì)提前初始化ServiceMethod,后面分析中會(huì)做介紹
分析完Retrofit中的成員變量之后,我們來看一下Builder如何初始化這些成員變量,先看一下Builder的構(gòu)造方法:
public Builder() {
this(Platform.get());
}
需要傳一個(gè)Platform對(duì)象:
class Platform {
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方法返回PLATFORM成員,而這個(gè)成員通過findPlatform方法初始化,我們使用的是Android平臺(tái),所以直接返回一個(gè)Android對(duì)象,接下來看一下Platform的靜態(tài)內(nèi)部類Android的定義:
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
Platform的作用是幫助初始化Retrofit。而不同的平臺(tái)會(huì)使用不同的對(duì)象去初始化Retrofit,我們只關(guān)心Android平臺(tái)。
接下來看一下Builder的build方法:
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
build方法會(huì)初始化Retrofit大部分成員:
- baseUrl:我們通過builder對(duì)象手動(dòng)設(shè)置,例子中的是Config.DEVICE_HOST,只需要知道,這是一個(gè)host就可以
- callFactory:我們通過builder設(shè)置的OkHttpClient對(duì)象
- callExecutor:platform.defaultCallbackExecutor,Android平臺(tái)是MainThreadExecutor類型,它是主線程線程池,所有的請(qǐng)求都是在主線程發(fā)送一個(gè)消息,在異步線程中執(zhí)行請(qǐng)求,最后在主線程中處理回調(diào)
- adapterFactories:添加一個(gè)ExecutorCallAdapterFactory,而我們又通過bulder設(shè)置了一個(gè)RxJavaCallAdapterFactory,所以adapterFactories中有兩個(gè)元素,最后會(huì)使用到RxJavaCallAdapterFactory
- converterFactories:通過builder設(shè)置,是JacksonConverterFactory類型
- validateEagerly:默認(rèn)為false
可以看到,在Retrofit.Builder.build方法中,初始化了Retrofit所有的成員。
至此,構(gòu)建Retrofit對(duì)象的過程介紹完畢??偨Y(jié)一下,就是創(chuàng)建了一個(gè)Retrofit對(duì)象,并且初始化了它的所有成員變量。
2. 創(chuàng)建Service實(shí)例
Retrofit對(duì)象初始化之后,就會(huì)初始化Service對(duì)象,代碼如下:
mService = retrofit.create(DeviceService.class);
Retrofit調(diào)用create方法初始化Service對(duì)象:
public <T> T create(final Class<T> 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);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
這段代碼中,我們著重看兩個(gè)地方:
饑餓模式
如果validateEagerly為true,就會(huì)調(diào)用eagerlyValidateMethod方法:
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
這個(gè)方法通過反射,獲取Service中定義的所有方法,并且遍歷,對(duì)每個(gè)方法做loadServiceMethod處理,而loadServiceMethod就是為一個(gè)方法創(chuàng)建一個(gè)ServiceMethod對(duì)象,可見validateEagerly的作用就是提前初始化Service方法對(duì)應(yīng)的ServiceMethod。
至于ServiceMethod是什么,我們后面分析。
動(dòng)態(tài)代理
使用動(dòng)態(tài)代理模式構(gòu)建Service實(shí)例,了解動(dòng)態(tài)代理的同學(xué)知道,動(dòng)態(tài)代理可以自動(dòng)幫我們生成代理類,我們調(diào)用代理類的方法,最后都會(huì)調(diào)用到InvocationHandler的invoke方法,它的好處在于可以對(duì)所有方法做統(tǒng)一處理。
而Retrofit正是需要對(duì)Service的方法做統(tǒng)一處理:
- 判斷方法是否屬于Object,如果是的,直接調(diào)用方法
- 判斷方法是否為platform的默認(rèn)方法,Android平臺(tái)都返回false
- 方法屬于Service,則會(huì)執(zhí)行以下三句代碼(因?yàn)槭茿ndroid平臺(tái),所以肯定會(huì)走到這里):
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
到這里,創(chuàng)建Service實(shí)例完畢。總結(jié)一下,Retrofit通過動(dòng)態(tài)代理的方式初始化一個(gè)實(shí)現(xiàn)了Service的代理類。
3.ServiceMethod對(duì)象
Retrofit和Service初始化之后,我們嘗試進(jìn)行一次請(qǐng)求,即調(diào)用一次Service的方法,它的流程是什么樣的呢?
這就要回到上面介紹的動(dòng)態(tài)代理,每次調(diào)用service方法最后都會(huì)執(zhí)行InvocationHandler.invoke方法,這個(gè)方法對(duì)所有的請(qǐng)求做統(tǒng)一處理,即上面提到的三句代碼,下面逐句分析:
第一句:構(gòu)建一個(gè)ServiceMethod對(duì)象
ServiceMethod serviceMethod = loadServiceMethod(method);
在饑餓模式中也提到了loadServiceMethod方法的,這個(gè)方法會(huì)接收method作為參數(shù),返回一個(gè)ServiceMethod對(duì)象:
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;
}
先從serviceMethodCache找是否存在該方法對(duì)應(yīng)的ServiceMethod,如果沒有,創(chuàng)建一個(gè)ServiceMethod對(duì)象,并且把<method, MethodService>保存到serviceMethodCache中,下次調(diào)該方法就可以直接從serviceMethodCache中獲取ServiceMethod,而不用重復(fù)創(chuàng)建,提高性能。
ServiceMethod也采用Builder模式來創(chuàng)建對(duì)象,我們先看一下ServiceMethod的定義:
/** Adapts an invocation of an interface method into an HTTP call. */
final class ServiceMethod<T> {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
final okhttp3.Call.Factory callFactory;
final CallAdapter<?> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, T> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
ServiceMethod(Builder<T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
}
ServiceMethod的類注釋介紹了它的作用,就是把一次接口的方法調(diào)用轉(zhuǎn)換成一個(gè)Http請(qǐng)求。它也包含了很多成員變量,都是與Http請(qǐng)求有關(guān)的一些參數(shù),在Builder.build方法中會(huì)初始化這些參數(shù):
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
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();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
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];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
可以看出ServiceMethod的build()方法里面主要做的事情是callAdapter, responseConverter實(shí)例的獲取,以及解析方法注解,我們來看下callAdapter的實(shí)例是怎么獲取的
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
...
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
可以看出還是要調(diào)用retrofit的callAdapter方法
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
...
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;
}
}
...
代碼片段省略了部分,最后還是會(huì)走到nextCallAdapter方法去獲取其實(shí)例,callAdapter實(shí)例會(huì)從adapterFactories獲取,由于獲取的是一個(gè)工廠類還是要調(diào)用一個(gè)get方法從工廠獲取其callAdapter對(duì)象。adapterFactories就是我們獲取Retrofit實(shí)例時(shí)候傳入的,可以自定義,也可以用別人提供的,先設(shè)置的滿足條件,先會(huì)被使用。
responseConverter也是一樣的方法去獲取其實(shí)例。
下面列舉一下ServiceMethod的成員變量及構(gòu)造過程中初始化情況:
- callFactory:跟Retrofit.callFactory一樣,即OkHttpClient
- callAdapter:根據(jù)方法的返回類型,從Retrofit的兩個(gè)callFactory中匹配得到RxJavaCallAdapterFactory,具體匹配過程同學(xué)們可以自行跟蹤代碼。通過RxJavaCallAdapterFactory創(chuàng)建該方法對(duì)應(yīng)的RxJavaCallAdapterFactory.SimpleCallAdapter
- baseUrl:同Retrofit的baseUrl一致
- responseConverter:通過Retrofit的converterFactory創(chuàng)建的JacksonResponseBodyConverter對(duì)象
- httpMethod:從方法注解中解析得到,即GET、POST等Http請(qǐng)求類型
- relativeUrl:請(qǐng)求地址,一般是從請(qǐng)求類型注解中解析得到,如@GET("order/query/101")對(duì)應(yīng)的relativeUrl是order/query/101
- header:請(qǐng)求頭信息,從方法注解@Headers中解析得到
- contentType:請(qǐng)求的數(shù)據(jù)類型,從@Headers中解析得到
- hasBody:請(qǐng)求是否有內(nèi)容部分(body),DELETE/GET/HEAD/OPTIONS類型的請(qǐng)求沒有,POST/PATCH/PUT類型請(qǐng)求有
- isFormEncoded:從方法上是否有@FormUrlEncoded判斷,不能與@Multipart同時(shí)存在,前提條件是hasBody=true
- isMultipart:從方法上是否有@Multipart判斷,不能與@FormUrlEncoded同時(shí)存在,前提條件是hasBody=true
- parameterHandlers:數(shù)組類型,從方法的參數(shù)注解解析得到,數(shù)量與方法參數(shù)數(shù)量一直,作用是參數(shù)信息設(shè)置到Http請(qǐng)求構(gòu)造器RequestBuilder中
可以看到,loadServiceMethod方法就是根據(jù)method構(gòu)建一個(gè)ServiceMethod對(duì)象。在構(gòu)建的過程中,解析方法上的注解和參數(shù)注解,初始化ServiceMethod的所有成員變量。
具體的解析過程不詳細(xì)介紹,代碼比較多,對(duì)著可以自己參照源碼學(xué)習(xí)。
第二句:創(chuàng)建OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall是Call的實(shí)現(xiàn)類,定義如下:
final class OkHttpCall<T> implements Call<T> {
private final ServiceMethod<T> serviceMethod;
private final Object[] args;
private volatile boolean canceled;
// All guarded by this.
private okhttp3.Call rawCall;
private Throwable creationFailure; // Either a RuntimeException or IOException.
private boolean executed;
OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
//省略其他代碼
}
從定義中可知,OkHttpCall構(gòu)造方法接收ServiceMethod和參數(shù)數(shù)組,并且還有還有一個(gè)成員rawCall(okhttp3.Call類型),它的作用是執(zhí)行請(qǐng)求并且管理請(qǐng)求的狀態(tài)和處理請(qǐng)求回調(diào)。
第三句:執(zhí)行請(qǐng)求
return serviceMethod.callAdapter.adapt(okHttpCall);
調(diào)用了callAdapter.adapt方法,而serviceMethod.callAdapter是RxJavaCallAdapterFactory.SimpleCallAdapter對(duì)象,所以我們直接看SimpleCallAdapter的adapt方法:
static final class SimpleCallAdapter implements CallAdapter<Observable<?>> {
private final Type responseType;
private final Scheduler scheduler;
SimpleCallAdapter(Type responseType, Scheduler scheduler) {
this.responseType = responseType;
this.scheduler = scheduler;
}
@Override public Type responseType() {
return responseType;
}
@Override public <R> Observable<R> adapt(Call<R> call) {
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));
}
});
if (scheduler != null) {
return observable.subscribeOn(scheduler);
}
return observable;
}
}
用CallOnSubscribe構(gòu)建了一個(gè)Observable對(duì)象,看一下CallOnSubscribe的實(shí)現(xiàn):
static final class CallOnSubscribe<T> implements Observable.OnSubscribe<Response<T>> {
private final Call<T> originalCall;
CallOnSubscribe(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override public void call(final Subscriber<? super Response<T>> subscriber) {
// Since Call is a one-shot type, clone it for each new subscriber.
final Call<T> call = originalCall.clone();
// Attempt to cancel the call if it is still in-flight on unsubscription.
subscriber.add(Subscriptions.create(new Action0() {
@Override public void call() {
call.cancel();
}
}));
try {
Response<T> response = call.execute();
if (!subscriber.isUnsubscribed()) {
subscriber.onNext(response);
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (!subscriber.isUnsubscribed()) {
subscriber.onError(t);
}
return;
}
if (!subscriber.isUnsubscribed()) {
subscriber.onCompleted();
}
}
}
CallOnSubscribe實(shí)現(xiàn)了rxjava中的Observable.OnSubscribe接口,當(dāng)Observable對(duì)象調(diào)用subscribe方法的時(shí)候,就會(huì)執(zhí)行OnSubscribe的call方法(可參照RxJava源碼)。
call方法中著重關(guān)注call.execute()這句代碼,這里的call是上面提到的的OkHttpCall對(duì)象,所以看OkHttpCall的execute方法:
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
if (creationFailure != null) {
if (creationFailure instanceof IOException) {
throw (IOException) creationFailure;
} else {
throw (RuntimeException) creationFailure;
}
}
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
主要邏輯:檢查call是否為空,如果為空,則調(diào)用createRawCall方法創(chuàng)建call對(duì)象(okhttp3.Call),然后調(diào)用call.execute()方法,并且用convert把響應(yīng)結(jié)果轉(zhuǎn)換為Response對(duì)象。
這段代碼我們關(guān)注兩個(gè)點(diǎn):a. 初始化call對(duì)象 b. 調(diào)用call.execute方法執(zhí)行請(qǐng)求。下面一次介紹:
a. 初始化call對(duì)象
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
先把ServiceMethod轉(zhuǎn)化為Request對(duì)象,然后用Request構(gòu)建一個(gè)okhttp3.Call對(duì)象,serviceMethod.callFactory是OkHttpClient對(duì)象,跟蹤到OkHttpClient.newCall方法:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
這里創(chuàng)建了一個(gè)RealCall對(duì)象,它是OkHttp中Call的實(shí)現(xiàn)類,是真正的請(qǐng)求類。
b. 調(diào)用call.execute方法執(zhí)行請(qǐng)求
真正的請(qǐng)求類是RawCall,所以我們直接看RawCall的execute方法:
@Override public Response execute() throws IOException {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
eventListener.callStart(this);
try {
client.dispatcher().executed(this);
Response result = getResponseWithInterceptorChain();
if (result == null) throw new IOException("Canceled");
return result;
} catch (IOException e) {
eventListener.callFailed(this, e);
throw e;
} finally {
client.dispatcher().finished(this);
}
}
這段代碼就涉及到OkHttp的請(qǐng)求機(jī)制,這里不做解釋,如果有不理解的同學(xué),自行補(bǔ)習(xí)。
總之執(zhí)行了請(qǐng)求之后,會(huì)生成一個(gè)okhttp3.Response對(duì)象,然后通過OkHttpCall.parseResponse方法把okhttp3.Response轉(zhuǎn)換為retrofit2.Response類型:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
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);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
這里返回的Response交給RxJava處理,最后返回給客戶端。到此,一個(gè)請(qǐng)求的整個(gè)流程就介紹完畢了。
Retrofit中使用了大量的設(shè)計(jì)模式,下面是從網(wǎng)上找的一張圖
