簡(jiǎn)介
剛接觸Retrofit的時(shí)候,就寫了一篇簡(jiǎn)單的使用介紹:Retrofit 2.0基本使用方法,算是對(duì)Retrofit的基礎(chǔ)入門。也算是接觸Retrofit一段時(shí)間了,現(xiàn)在差不多可以對(duì)源碼層進(jìn)行解析,最起碼,理解原理后可以使得我們使用起來更加得心應(yīng)手 _。
網(wǎng)絡(luò)請(qǐng)求使用基本方法
參考官網(wǎng):
Introduction
Retrofit turns your HTTP API into a Java interface.
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
The Retrofit class generates an implementation of the GitHubService interface.
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.
Call<List<Repo>> repos = service.listRepos("octocat");
//synchronous request
repos.execute();
//asynchronous request
repos.enqueue(new Callback<ResponseBody>() {/***/});
Use annotations to describe the HTTP request:
URL parameter replacement and query parameter support
Object conversion to request body (e.g., JSON, protocol buffers)
Multipart request body and file upload
源碼解析: retrofit:2.3.0
從上一節(jié)的使用Retrofit進(jìn)行網(wǎng)絡(luò)請(qǐng)求中,我們可以看到,請(qǐng)求過程主要分為以下幾步:
- 創(chuàng)建一個(gè)接口進(jìn)行HTTP請(qǐng)求描述;
- 使用
Retrofit.Builder構(gòu)建模式構(gòu)造出一個(gè)Retrofit實(shí)例; - 調(diào)用
retrofit.create()方法獲取請(qǐng)求接口實(shí)例; - 由請(qǐng)求接口實(shí)例獲取到
Call對(duì)象; - 進(jìn)行網(wǎng)絡(luò)請(qǐng)求(同步/異步)
接下來,我們就按照以上正常的網(wǎng)絡(luò)請(qǐng)求順序來對(duì)Retrofit源碼進(jìn)行解析。
-
創(chuàng)建一個(gè)接口進(jìn)行HTTP請(qǐng)求描述
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
這里主要做的就是采用注解的方式進(jìn)行HTTP描述,后面在第4步由請(qǐng)求接口實(shí)例獲取到Call對(duì)象時(shí)進(jìn)行反射提取注解內(nèi)容進(jìn)行HTTP請(qǐng)求構(gòu)造(如果開啟了預(yù)先加載解析(validateEagerly=true),那么在第3步調(diào)用retrofit.create()方法獲取請(qǐng)求接口實(shí)例的時(shí)候就會(huì)進(jìn)行注解解析),具體解析方法參考后續(xù)分析。
-
使用Retrofit.Builder構(gòu)建模式構(gòu)造出一個(gè)Retrofit實(shí)例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
那我們就先來看下Retrofit.Builder部分源碼:
/**
* Build a new {@link Retrofit}.
* <p>
* Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods
* are optional.
*/
public static final class Builder {
private final Platform platform;
//callFactory通過newCall(Request request)方法,返回一個(gè)okhttp3.Call對(duì)象,以便讓我們進(jìn)行實(shí)際的HTTP請(qǐng)求
//也就是說callFactory是我們用來生成一個(gè)客戶端HTTP請(qǐng)求工廠實(shí)例
private @Nullable okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
//converterFactories生產(chǎn)Converter<F, T>,用于將HTTP返回結(jié)果F類型轉(zhuǎn)換為T類型,或?qū)TTP請(qǐng)求類型F轉(zhuǎn)換為T。
private final List<Converter.Factory> converterFactories = new ArrayList<>();
//adapterFactories生產(chǎn) CallAdapter<R, T>,用于將retrofit2.Call<R>網(wǎng)絡(luò)請(qǐng)求類型轉(zhuǎn)換為T類型:T adapt(Call<R> var1);
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private @Nullable
Executor callbackExecutor;
private boolean validateEagerly;
···
···
···
}
從Retrofit.Builder的注釋中,我們可以看到,在調(diào)用Retrofit.Builder.build()之前,除了baseUrl()是必須配置的以外,其他的內(nèi)容都是可選配置。
這里要對(duì)兩個(gè)類型做下講解,因?yàn)楣P者在剛分析Retrofit源碼時(shí),被這兩個(gè)類型的概念弄得頭暈眼脹,好在一頓分析后,終于有了一點(diǎn)眉目,這兩個(gè)類型就是:Converter<F, T>和CallAdapter<R, T>。
Converter<F, T>:數(shù)據(jù)轉(zhuǎn)換器,用來將HTTP請(qǐng)求返回結(jié)果由F類型轉(zhuǎn)換為T類型,或者將HTTP請(qǐng)求類型F轉(zhuǎn)換為T
/**
* Convert objects to and from their representation in HTTP. Instances are created by {@linkplain
* Factory a factory} which is {@linkplain Retrofit.Builder#addConverterFactory(Factory) installed}
* into the {@link Retrofit} instance.
*/
public interface Converter<F, T> {
T convert(F value) throws IOException;
···
···
···
}
舉例:
new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
上面配置了ConverterFactory為GsonConverterFactory,那么當(dāng)HTTP請(qǐng)求結(jié)果返回時(shí),就會(huì)由GsonConverterFactory產(chǎn)生的Converter,假設(shè)為Converter<ResponseBody, List<Repo>>,該Converter就會(huì)將HTTP返回結(jié)果ResponseBody轉(zhuǎn)換為 List<Repo>。
而若是將對(duì)象轉(zhuǎn)換為數(shù)據(jù),那么假設(shè)類型為:Converter< List<Repo>, RequestBody>,該Converter在構(gòu)建請(qǐng)求體時(shí),會(huì)將List<Repo>轉(zhuǎn)換為RequestBody對(duì)象。
CallAdapter<R, T>:請(qǐng)求適配器,用于將retrofit2.Call<R>網(wǎng)絡(luò)請(qǐng)求類型轉(zhuǎn)換為T類型
/**
* Adapts a {@link Call} with response type {@code R} into the type of {@code T}. Instances are
* created by {@linkplain Factory a factory} which is
* {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into the {@link Retrofit}
* instance.
*/
public interface CallAdapter<R, T> {
/**
* Returns the value type that this adapter uses when converting the HTTP response body to a Java
* object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type
* is used to prepare the {@code call} passed to {@code #adapt}.
* <p>
* Note: This is typically not the same type as the {@code returnType} provided to this call
* adapter's factory.
*/
Type responseType();
/**
* Returns an instance of {@code T} which delegates to {@code call}.
* <p>
* For example, given an instance for a hypothetical utility, {@code Async}, this instance would
* return a new {@code Async<R>} which invoked {@code call} when run.
* <pre><code>
* @Override
* public <R> Async<R> adapt(final Call<R> call) {
* return Async.create(new Callable<Response<R>>() {
* @Override
* public Response<R> call() throws Exception {
* return call.execute();
* }
* });
* }
* </code></pre>
*/
T adapt(Call<R> call);
/**
* Creates {@link CallAdapter} instances based on the return type of {@linkplain
* Retrofit#create(Class) the service interface} methods.
*/
···
···
···
}
舉例:
new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
上面配置了CallAdapterFactory為RxJava2CallAdapterFactory,這里的作用就是將Retrofit2.Call<T>對(duì)象轉(zhuǎn)換為Observable<T>類型,所以如果配置了RxJava2CallAdapterFactory,那么接口方法聲明應(yīng)該改為如下形式:
public interface GitHubService {
@GET("users/{user}/repos")
Observable<List<Repo>> listRepos(@Path("user") String user);
}
其實(shí)這個(gè)addCallAdapterFactory實(shí)現(xiàn)原理是挺簡(jiǎn)單的,因?yàn)?code>Retrofit里面維護(hù)了CallAdapter.Factory一個(gè)數(shù)組,在使用Builder配置的時(shí)候,所有配置的CallAdapter.Factory最后都會(huì)保存到Retrofit那個(gè)數(shù)組中,后面在進(jìn)行轉(zhuǎn)換是,Retrofit會(huì)根據(jù)接口方法返回結(jié)果類型(此處為:Observable<List<Repo>>),遍歷CallAdapter.Factory數(shù)組,找到一個(gè)能處理該返回類型的CallAdapter后,就不再遍歷。更多具體的解析方法請(qǐng)參考后續(xù)整體流程的介紹。
上面講了那么多的東西,可是還是沒有講到Retrofit實(shí)例的創(chuàng)建,別著急,在查看Retrofit.Builder.build()方法前,我們還要看下Builder的構(gòu)造函數(shù):
Builder(Platform platform) {
this.platform = platform;
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
}
public Builder() {
this(Platform.get());
}
當(dāng)我們調(diào)用:
new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
就會(huì)走入:Builder()--> Builder(Platform platform)
然后我們看到,在Builder(Platform platform)構(gòu)造函數(shù)里面,會(huì)往converterFactories里面添加進(jìn)一個(gè)BuiltInConverters對(duì)象,所以默認(rèn)的ConverterFactory就是BuiltInConverters。前面說過ConverterFactory主要是用來將HTTP返回結(jié)果進(jìn)行類型轉(zhuǎn)換或者將HTTP請(qǐng)求體進(jìn)行類型轉(zhuǎn)換,然后我們看下BuiltInConverters是怎樣的轉(zhuǎn)換方式:
final class BuiltInConverters extends Converter.Factory {
//返回結(jié)果轉(zhuǎn)換
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
if (type == ResponseBody.class) {
//如果annotations是Streaming類型
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
//請(qǐng)求轉(zhuǎn)換
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();
@Override public Void convert(ResponseBody value) throws IOException {
value.close();
return null;
}
}
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
@Override public RequestBody convert(RequestBody value) throws IOException {
return value;
}
}
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) throws IOException {
return value;
}
}
static final class BufferingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) throws IOException {
try {
// Buffer the entire body to avoid future I/O.
return Utils.buffer(value);
} finally {
value.close();
}
}
}
static final class ToStringConverter implements Converter<Object, String> {
static final ToStringConverter INSTANCE = new ToStringConverter();
@Override public String convert(Object value) {
return value.toString();
}
}
}
返回結(jié)果轉(zhuǎn)換的時(shí)候,有3種情況:
- 如果返回類型是
ResponseBody類型,那么可能返回的是:StreamingResponseBodyConverter.INSTANCE或者BufferingResponseBodyConverter.INSTANCE,再跟蹤進(jìn)去這兩個(gè)類里面的convert函數(shù):
@Override public ResponseBody convert(ResponseBody value){···}
發(fā)現(xiàn)傳入的是ResponseBody,返回的也是ResponseBody(BufferingResponseBodyConverter里面有進(jìn)行特殊處理,主要是為了去除future I/O),所以我們可以認(rèn)為BuiltInConverters對(duì)HTTP返回結(jié)果沒有進(jìn)行轉(zhuǎn)換處理。
- 如果返回類型是
Void類型,那么最終就將ResponseBody資源關(guān)閉后,直接返回null。 - 如果返回類型不是
ResponseBody和Void類型,直接返回null。
同理,我們來看下請(qǐng)求體轉(zhuǎn)換:
//請(qǐng)求轉(zhuǎn)換
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
@Override public RequestBody convert(RequestBody value) throws IOException {
return value;
}
}
可以看到,如果是RequestBody類型,那就不轉(zhuǎn)換,如果不是RequestBody類型,直接返回null。
綜上所述:BuiltInConverters只能響應(yīng)ResponseBody和RequestBody,但是并不進(jìn)行任何轉(zhuǎn)換.對(duì)于其他類型,統(tǒng)統(tǒng)返回null。
到這里,終于可以走進(jìn)Retrofit.Builder.build()函數(shù),一窺究竟:
/**
* Create the {@link Retrofit} instance using the configured values.
* <p>
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
//callFactory默認(rèn)為OkHttpClient
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
//默認(rèn)的callbackExecutor為Platform.Android.MainThreadExecutor
//MainThreadExecutor繼承Executor,并復(fù)寫execute(Runnable r),
// execute內(nèi)部直接通過主線程Handler.post(r),即r.run發(fā)生在主線程
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//defaultCallAdapterFactory是ExecutorCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
//BuiltInConverters在Retrofit.Builder(Platform)構(gòu)造時(shí),已被傳入
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
build函數(shù)一進(jìn)去,就看到:
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
這說明baseUrl是一定要進(jìn)行配置的,否則程序就會(huì)拋出異常,這跟我們上面講到的一致。
接著往下看:
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
//callFactory默認(rèn)為OkHttpClient
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
//默認(rèn)的callbackExecutor為Platform.Android.MainThreadExecutor
//MainThreadExecutor繼承Executor,并復(fù)寫execute(Runnable r),
// execute內(nèi)部直接通過主線程Handler.post(r),即r.run發(fā)生在主線程
callbackExecutor = platform.defaultCallbackExecutor();
}
這里可以看到,如果沒有配置okhttp3.Call.Factory,那么就會(huì)使用默認(rèn)的HTTP工廠類:OkHttpClient,用于客戶端程序創(chuàng)建okhttp3.Call對(duì)象,以進(jìn)行實(shí)際的HTTP網(wǎng)絡(luò)請(qǐng)求。
如果沒有線程調(diào)度器callbackExecutor,那么就會(huì)使用默認(rèn)的線程調(diào)度器:Platform.Android.MainThreadExecutor:
static class Android extends Platform {
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
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);
}
}
}
從源碼可以看出,默認(rèn)的線程調(diào)度器是主線程調(diào)度器。
接下來再看:
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//defaultCallAdapterFactory是ExecutorCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
可以看到,這里為adapterFactories增加了一個(gè)CallAdapterFactory:
//Platform.java
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
//ExecutorCallAdapterFactory.java
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
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<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}
@Override
public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
static final class ExecutorCallbackCall<T> implements retrofit2.Call<T> {
final Executor callbackExecutor;
//HTTP請(qǐng)求委托類
final retrofit2.Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
//異步請(qǐng)求
@Override
public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override
public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override
public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override
public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
//同步請(qǐng)求
@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
···
···
···
}
在Android平臺(tái)上,callbackExecutor默認(rèn)不為null,所以defaultCallAdapterFactory返回的是ExecutorCallAdapterFactory。從ExecutorCallAdapterFactory的get函數(shù),可以看到,ExecutorCallAdapterFactory只會(huì)響應(yīng)返回類型為Call的函數(shù)聲明(所以,如果我們沒有配置addCallAdapterFactory(),那么我們接口函數(shù)聲明的返回類型必須為Call<?>),響應(yīng)處理的最終結(jié)果就是返回一個(gè)CallAdapter,這個(gè)CallAdapter的adapt()函數(shù)會(huì)傳入一個(gè)HTTP請(qǐng)求委托類,然后返回一個(gè)HTTP請(qǐng)求代理類:ExecutorCallbackCall<T> implements retrofit2.Call<T>,這個(gè)代理類代理了委托類的異步HTTP網(wǎng)絡(luò)請(qǐng)求,并將返回結(jié)果通過線程調(diào)度器將回調(diào)監(jiān)聽函數(shù)分發(fā)到具體線程上執(zhí)行(默認(rèn)線程調(diào)度器是主線程調(diào)度)。
講到這里,Retrofit實(shí)例的配置創(chuàng)建就算是完成了。下面這個(gè)圖展示了Retrofit.Builder提供的配置選項(xiàng):
-
調(diào)用retrofit.create()方法獲取請(qǐng)求接口實(shí)例
GitHubService service = retrofit.create(GitHubService.class);
那我們接下來就看一下create()的源碼:
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
//1.是否是接口
//2.不能繼承其他接口
Utils.validateServiceInterface(service);
//預(yù)先加載解析注解:loadServiceMethod
//默認(rèn)false,即調(diào)用接口方法后,才進(jìn)行解析
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, @Nullable 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);
}
//java8平臺(tái)使用
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
這里我們可以看到,create方法返回的是一個(gè) (T) Proxy.newProxyInstance()方法產(chǎn)生的一個(gè)動(dòng)態(tài)代理對(duì)象(如果不清楚動(dòng)態(tài)代理,可以看下我之前寫的文章:Java代理模式,里面對(duì)java的動(dòng)態(tài)代理有詳細(xì)講解)。使用該動(dòng)態(tài)代理對(duì)象進(jìn)行方法調(diào)用后,會(huì)自動(dòng)被InvocationHandler攔截,最終進(jìn)入InvocationHandler的invoke函數(shù)里面。
-
由請(qǐng)求接口實(shí)例獲取到Call對(duì)象
Call<List<Repo>> repos = service.listRepos("octocat")
從上面create的分析中,我們知道,此處的service是一個(gè)動(dòng)態(tài)代理類對(duì)象,所以,在調(diào)用方法時(shí),會(huì)被InvocationHandler的invoke方法攔截,所以調(diào)用:service.listRepos("octocat")就會(huì)進(jìn)入InvocationHandler.invoke()中,查看下invoke函數(shù),最主要的操作就是如下3句話:
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
ServiceMethod在Retrofit中是一個(gè)很重要的類,主要做的就是對(duì)接口方法注解進(jìn)行解析,最終生成一個(gè)Request。
那我們先來看下loadServiceMethod()源碼:
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
serviceMethodCache是一個(gè)緩存容器,是對(duì)接口方法的解析緩存。
//class Retrofit
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
從loadServiceMethod()中可以看到,ServiceMethod的實(shí)例也是通過builder模式進(jìn)行構(gòu)建的,構(gòu)建過程需傳入Retrofit對(duì)象和Method對(duì)象。
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//取得接口方法的注解
this.methodAnnotations = method.getAnnotations();
//返回接口方法參數(shù)類型
this.parameterTypes = method.getGenericParameterTypes();
//返回接口方法各個(gè)參數(shù)注解
//按參數(shù)聲明順序排列,每個(gè)參數(shù)可能有多個(gè)注解,故二維數(shù)組
//parameterAnnotationsArray[0][i]:第一個(gè)參數(shù)第i個(gè)注解
//parameterAnnotationsArray[1][j]:第二個(gè)參數(shù)第j個(gè)注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
//CallAdapter<T, R> callAdapter;適配Call的響應(yīng)類型,將默認(rèn)響應(yīng)類型R轉(zhuǎn)換為類型T
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?");
}
//Converter<ResponseBody, T> responseConverter;HTTP交互中,轉(zhuǎn)換對(duì)象為數(shù)據(jù) 或 從數(shù)據(jù)轉(zhuǎn)換為對(duì)象
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
···
···
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);
}
···
···
return new ServiceMethod<>(this);
}
在ServiceMethod.Builder.build()源碼中可以看到:
callAdapter = createCallAdapter();
首先創(chuàng)建一個(gè)callAdapter,具體創(chuàng)建過程如下:
private CallAdapter<T, R> createCallAdapter() {
//接口方法return類型
Type returnType = method.getGenericReturnType();
···
···
Annotation[] annotations = method.getAnnotations();
//noinspection unchecked
···
···
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
}
可以看到,其最終調(diào)用到的是retrofit.callAdapter():
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
/**
* Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
* #callAdapterFactories() factories} except {@code skipPast}.
*
* @throws IllegalArgumentException if no call adapter available for {@code type}.
*/
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
// final List<CallAdapter.Factory> adapterFactories;
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;
}
}
//throw exception
···
···
}
可以看到,createCallAdapter()就是從Retrofit的List<CallAdapter.Factory> adapterFactories數(shù)組中,遍歷找到一個(gè)可以處理該接口方法返回類型和注解的CallAdapter<?, ?>。那根據(jù)我們之前的分析,如果我們沒有進(jìn)行CallAdapter的配置,那么默認(rèn)的CallAdapter就是ExecutorCallAdapterFactory.get(Call.class,xxx,retrofit);
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if(getRawType(returnType) != Call.class) {
return null;
} else {
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
public Type responseType() {
return responseType;
}
public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallAdapterFactory.ExecutorCallbackCall(ExecutorCallAdapterFactory.this.callbackExecutor, call);
}
};
}
}
可以看到,默認(rèn)的CallAdapter.Factory只會(huì)響應(yīng)接口方法返回類型為Call,所以遍歷adapterFactories的時(shí)候,如果接口方法返回類型不是Call,那么ExecutorCallAdapterFactory.get()自然返回的就是null,然后就會(huì)繼續(xù)找下一個(gè)CallAdapterFactory,繼續(xù)嘗試,直到找到能處理該接口方法返回類型的CallAdapterFactory,由其返回一個(gè)CallAdapter。
上面的流程可以這樣想(較為生動(dòng)):
createCallAdapter說:retrofit,給我一個(gè)能處理我這個(gè)接口方法返回類型(假設(shè)為Observable<T>)的CallAdapter。
retrofit接收到請(qǐng)求后,就會(huì)從自己的adapterFactories倉(cāng)庫(kù)中一個(gè)一個(gè)的進(jìn)行詢問:
首先找到默認(rèn)的CallAdapter.Factory:ExecutorCallAdapterFactory,然后說:ExecutorCallAdapterFactory啊,你能處理Observable<T>這個(gè)返回類型嗎?
ExecutorCallAdapterFactory一看,說:retrofit啊,你給我的返回類型不是Call類型,我沒辦法處理,你找下一位CallAdapter.Factory仁兄吧。
既然默認(rèn)的ExecutorCallAdapterFactory沒辦法處理這個(gè)接口方法返回類型,那retrofit就只能繼續(xù)問下一位CallAdapter.Factory啦,假設(shè)下一位是RxJava2CallAdapterFactory,然后,retrofit開始發(fā)問,說:RxJava2CallAdapterFactory仁兄呀,你能處理Observable<T>這個(gè)返回類型嗎?
RxJava2CallAdapterFactory一看,說:retrofit兄啊,你這個(gè)Observable<T>我拿手呀,隨隨便便進(jìn)行處理,處理的結(jié)果拿到了這個(gè)CallAdapter,你趕緊拿著給createCallAdapter交差吧。
retrofit一聽,太高興了,說到:RxJava2CallAdapterFactory兄啊,您真牛逼,謝謝您了,好的好的,我趕緊拿著您給的CallAdapter給createCallAdapter交差,那邊催的緊呢。
于是,retrofit高高興興地就往createCallAdapter那邊趕了,adapterFactories后面還沒問到的兄弟就不管了,沒辦法,哥(retrofit)時(shí)間緊,沒有那么多時(shí)間去一 一問候兄弟們,望兄弟們見諒 _。
我們接著看ServiceMethod.Builder.build()方法,可以看到,createCallAdapter后,又createResponseConverter了:
//Converter<ResponseBody, T> responseConverter;HTTP交互中,轉(zhuǎn)換對(duì)象為數(shù)據(jù) 或 從數(shù)據(jù)轉(zhuǎn)換為對(duì)象
responseConverter = createResponseConverter();
responseConverter是Converter<ResponseBody, T>類型,其實(shí)我們一看到這個(gè),就應(yīng)該大概知道是怎么做了,肯定又是跟retrofit請(qǐng)求,retrofit又從倉(cāng)庫(kù)中進(jìn)行查找,只是這回是從List<Converter.Factory> converterFactories中查找,直到找到一個(gè)能處理這種responseType的Converter.Factory,由其返回一個(gè)Converter。讓我們看下源碼是不是這樣的:
//ServiceMethod.java
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
//Retrofit.java
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
/**
* Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
* {@linkplain #converterFactories() factories} except {@code skipPast}.
*
* @throws IllegalArgumentException if no converter available for {@code type}.
*/
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
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) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
//throw exception
···
···
···
}
可以看到,跟我們上面所說的過程是一樣的。
還記得嗎,有一個(gè)默認(rèn)的retrofit2.Converter.Factory是:BuiltInConverters。那從BuiltInConverters得到的Converter<ResponseBody, T>是什么呢,根據(jù)我們之前的分析:
- 如果
responseType是ResponseBody類型,那么返回的還是ResponseBody(BufferingResponseBodyConverter有經(jīng)過一些處理); - 如果
responseType是Void類型,那么釋放ResponseBody資源,然后返回null; - 其他
responseType類型,直接返回null。
所以,如果我們沒有配置addConverterFactory,那么接口返回類型應(yīng)該聲明為Call<ResponseBody>或者Call<Void>這類型的,這樣,默認(rèn)的retrofit2.Converter.Factory才能進(jìn)行處理。
接著看Retrofit.Builder.build()方法,可以看到:
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
這個(gè)是一個(gè)很重要的操作,就是對(duì)接口方法進(jìn)行解析,追蹤進(jìn)去再看下解析源碼:
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
可以看到里面對(duì)很多方法都進(jìn)行了解析,這里,我們就只拿GET方法解析源碼來分析下解析流程,其余方法解析都是類似的:
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
···
···
···
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
按照官網(wǎng)那個(gè)例子,那么:this.relativeUrl = value = "users/{user}/repos",在parseHttpMethodAndPath最后,調(diào)用了 parsePathParameters(value):
/**
* Gets the set of unique path parameters used in the given URI. If a parameter is used twice
* in the URI, it will only show up once in the set.
*/
static Set<String> parsePathParameters(String path) {
Matcher m = PARAM_URL_REGEX.matcher(path);
Set<String> patterns = new LinkedHashSet<>();
while (m.find()) {
patterns.add(m.group(1));
}
return patterns;
}
這里采用正則表達(dá)式取出形如"{*}"這種結(jié)構(gòu)的內(nèi)容,保留在全局Set<String> relativeUrlParamNames集合里面。
像官網(wǎng)這個(gè)例子,當(dāng)程序來到parsePathParameters("users/{user}/repos")的時(shí)候,正則表達(dá)式就獲得了user這個(gè)字符串,并存儲(chǔ)到全局relativeUrlParamNames里面。這樣,接口方法的可變字符串就被記錄了起來,后續(xù)只要獲取到參數(shù)注解內(nèi)容的名字是一樣的(eg:@Path("user") String user,參數(shù)注解內(nèi)容是"user“),將參數(shù)轉(zhuǎn)換(Converter,默認(rèn)為StringConverter,轉(zhuǎn)換就是直接調(diào)用參數(shù)對(duì)象的toString()方法轉(zhuǎn)成字符串)放入方法路徑可成為一個(gè)真正的relativeUrl。
以上就是方法注解的解析過程。
但是接口方法參數(shù)的注解還沒進(jìn)行解析,那我們就繼續(xù)往下看ServiceMethod.Builder.build()方法,可以看到:
//有多少個(gè)參數(shù)帶注解
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
//參數(shù)類型
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
//參數(shù)對(duì)應(yīng)的注解數(shù)組
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
//根據(jù)參數(shù)類型和對(duì)應(yīng)注解集合進(jìn)行解析,封裝到parameterHandlers中
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
參數(shù)注解解析過程的最后調(diào)用了:parseParameter,這個(gè)方法會(huì)根據(jù)傳入的參數(shù)類型和對(duì)應(yīng)注解集合進(jìn)行解析,封裝成為ParameterHandler,將每個(gè)參數(shù)的注解解析最后都存入到parameterHandlers數(shù)組中,所以parameterHandlers[0]就是第一個(gè)帶注解的參數(shù)的解析內(nèi)容,parameterHandlers[1]就是第二個(gè)帶注解的參數(shù)的解析內(nèi)容····:
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
可以看到parseParameter主要做的就是遍歷參數(shù)的所有注解,一個(gè)一個(gè)進(jìn)行注解解析:parseParameterAnnotation,這個(gè)方法內(nèi)部代碼特別長(zhǎng),因?yàn)橛泻芏喾N注解需要分析,在這里,我們就只抽取出@Path的注解解析部分內(nèi)容:
//參數(shù)注解解析
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
····
····
····
else if (annotation instanceof Path) {
if (gotQuery) {
throw parameterError(p, "A @Path parameter must not come after a @Query.");
}
if (gotUrl) {
throw parameterError(p, "@Path parameters may not be used with @Url.");
}
if (relativeUrl == null) {
throw parameterError(p, "@Path can only be used with relative url on @%s", httpMethod);
}
gotPath = true;
Path path = (Path) annotation;
String name = path.value();
/**
* 有效性檢驗(yàn):
* 1.命名規(guī)范:必須符合正則:[a-zA-Z][a-zA-Z0-9_-]*
* 2.注解value必須存在relativeUrlParamNames方法變量,對(duì)應(yīng)起來
*/
validatePathName(p, name);
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Path<>(name, converter, path.encoded());
}
···
···
···
}
這里對(duì)@Path的解析最主要的就是獲取一個(gè)Converter<?, String>,獲取是通過retrofit.stringConverter():
/**
* Returns a {@link Converter} for {@code type} to {@link String} from the available
* {@linkplain #converterFactories() factories}.
*/
public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
for (int i = 0, count = converterFactories.size(); i < count; i++) {
Converter<?, String> converter =
converterFactories.get(i).stringConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<T, String>) converter;
}
}
// Nothing matched. Resort to default converter which just calls toString().
//noinspection unchecked
return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
}
同樣,這里是通過遍歷converterFactories,找到一個(gè)能處理這種類型type的Converter.Factory,返回一個(gè) Converter<?, String>,如果找不到,就使用BuiltInConverters.ToStringConverter.INSTANCE。查看下BuiltInConverters.ToStringConverter.INSTANCE源碼:
//BuiltInConverters.java
static final class ToStringConverter implements Converter<Object, String> {
static final ToStringConverter INSTANCE = new ToStringConverter();
@Override public String convert(Object value) {
return value.toString();
}
}
可以看到,默認(rèn)的StringConverter就是通過調(diào)用paramter對(duì)象的toString方法,直接將結(jié)果類型轉(zhuǎn)成String類型。
到這里,我們就明白了:
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
接口方法參數(shù)user的類型其實(shí)可以不用是String類型,就算是其他類型也可以,但是默認(rèn)的StringConverter調(diào)用該類型對(duì)象的toString方法返回的結(jié)果要符合你自己需求。
比如,我們現(xiàn)在自定義一個(gè)java bean:
public class StringWrapper {
private String content;
public StringWrapper(String content)
{
this.content = content;
}
@Override
public String toString() {
return content;
}
}
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") StringWrapper user);
}
這樣也是可以的,因?yàn)?code>StringWrapper.toString跟我們上面直接定義成的String最終結(jié)果是一樣的。
回到正題,parseParameterAnnotation中對(duì)@Path的解析最終會(huì)返回一個(gè)ParameterHandler.Path對(duì)象:
static final class Path<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
private final boolean encoded;
Path(String name, Converter<T, String> valueConverter, boolean encoded) {
this.name = checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
@Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) {
throw new IllegalArgumentException(
"Path parameter \"" + name + "\" value must not be null.");
}
builder.addPathParam(name, valueConverter.convert(value), encoded);
}
}
最后,參數(shù)解析所有的信息都放入到了全局?jǐn)?shù)據(jù)parameterHandlers中,沒個(gè)parameterHandlers[i]都包含了各個(gè)參數(shù)的所有注解解析信息。
到這里,
ServiceMethod.Builder.build()方法也算是解析完畢了。總結(jié)一下:ServiceMethod的創(chuàng)建過程主要做了幾件事:
- 根據(jù)接口方法返回類型,通過遍歷
retrofit的adapterFactories列表,找到適合的CallAdapter<T, R> callAdapter。 - 根據(jù)HTTP返回結(jié)果類型,通過遍歷
retrofit的converterFactories列表,找到適合的Converter<ResponseBody, T> responseConverter。 - 對(duì)接口方法注解進(jìn)行解析:
parseMethodAnnotation(Annotation annotation)。 - 對(duì)接口方法參數(shù)注解進(jìn)行解析:
parseParameter - 完成以上工作后,創(chuàng)建
ServiceMethod對(duì)象。
最后,用一張圖來表達(dá)下ServiceMethod的創(chuàng)建過程:

現(xiàn)在繼續(xù)分析
Retrofit.create中InvocationHandler的invoke剩余部分源碼:
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
這里創(chuàng)建了一個(gè)okHttpCall:
final class OkHttpCall<T> implements retrofit2.Call<T> {
···
···
@GuardedBy("this")
private @Nullable okhttp3.Call rawCall;
···
}
這里可以看到OkHttpCall內(nèi)部持有一個(gè)okhttp3.Call,所以其實(shí)OkHttpCall所進(jìn)行的HTTP請(qǐng)求實(shí)際上都是交由okhttp3.Call進(jìn)行的。
InvocationHandler的invoke最后返回了:
return serviceMethod.callAdapter.adapt(okHttpCall);
經(jīng)過前面的分析,假設(shè)我們對(duì)Retrofit沒有經(jīng)過特殊配置,即Retrofit采用默認(rèn)配置,那么:serviceMethod.callAdapter返回的就是默認(rèn)的ExecutorCallAdapterFactory.get(Call.class,annotations,retrofit)
//ExecutorCallAdapterFactory.java
@Override
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<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
serviceMethod.callAdapter.adapt(okHttpCall)返回的就是一個(gè)new ExecutorCallbackCall<>(callbackExecutor, okHttpCall)的對(duì)象。
static final class ExecutorCallbackCall<T> implements retrofit2.Call<T> {
final Executor callbackExecutor;
//HTTP請(qǐng)求委托類
final retrofit2.Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
這里可以看到,ExecutorCallbackCall就是okHttpCall的代理類,而okHttpCall又持有okhttp3.Call實(shí)例。因此,進(jìn)行HTTP請(qǐng)求的過程就明晰了:
ExecutorCallbackCall.enqueue-->okHttpCall.enqueue-->okhttp3.Call.enqueue
ExecutorCallbackCall持有的Executor callbackExecutor默認(rèn)是主線程調(diào)度器,會(huì)將ExecutorCallbackCall發(fā)送HTTP請(qǐng)求的返回結(jié)果回調(diào)到主線程上執(zhí)行。
那我們最后就來看一下發(fā)送網(wǎng)絡(luò)請(qǐng)求的具體過程。
-
進(jìn)行網(wǎng)絡(luò)請(qǐng)求(同步/異步)
網(wǎng)絡(luò)請(qǐng)求是通過我們得到的ExecutorCallbackCall<>(callbackExecutor, okHttpCall)對(duì)象進(jìn)行請(qǐng)求,這里就只看下異步請(qǐng)求過程:
repos.enqueue(new Callback<ResponseBody>() {/***/});
上面分析知道,ExecutorCallbackCall內(nèi)部封裝了網(wǎng)絡(luò)請(qǐng)求和線程調(diào)度作用,而實(shí)際起網(wǎng)絡(luò)請(qǐng)求作用的是OkHttpCall。
那我們就來看下OkHttpCall的異步網(wǎng)絡(luò)請(qǐng)求enqueue源碼:
@Override
public void enqueue(final Callback<T> callback) {
···
···
okhttp3.Call call;
···
···
call = rawCall = createRawCall();
···
···
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
···
···
callSuccess(response);
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
···
callback.onFailure(OkHttpCall.this, e);
···
}
···
···
}
}
可以看到,OkHttpCall里面是通過函數(shù)createRawCall獲得一個(gè)真正的能用于HTTP網(wǎng)絡(luò)請(qǐng)求的okhttp3.Call對(duì)象,那么我們就來看下createRawCall()源碼是怎樣構(gòu)建出一個(gè)okhttp3.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;
}
這里,我們先來看下:
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
serviceMethod.callFactory默認(rèn)就是retrofit的callFactory,也就是OkHttpClient,所以這里就是由OkHttpClient創(chuàng)建出一個(gè)真正用于進(jìn)行HTTP網(wǎng)絡(luò)請(qǐng)求的okhttp3.Call對(duì)象。
接下來我們回顧上一行代碼,可以看到是通過serviceMethod.toRequest(args)構(gòu)建出一個(gè)Request,此處的args就是我們接口方法的參數(shù),那么我們就先來看下serviceMethod.toRequest源碼是怎樣構(gòu)建一個(gè)Request的:
/** Builds an HTTP request from method arguments. */
Request toRequest(@Nullable Object... args) throws IOException {
//從接口方法注解解析信息
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
//接口方法參數(shù)注解解析信息
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
所以我們前面為什么說ServiceMethod在Retrofit里面是很重要的,在這里也可以知道,ServiceMethod既負(fù)責(zé)解析接口方法,接口參數(shù),又負(fù)責(zé)從retrofit那邊獲取合適的CallAdapter和Converter,又要負(fù)責(zé)將接口解析出來的內(nèi)容組裝成一個(gè)HTTP Request···可以說,ServiceMethod就是Retrofit的核心引擎。
回到toRequest函數(shù),從上面的源碼中可以看到,首先是根據(jù)接口方法解析的信息組裝成了一個(gè)RequestBuilder,然后再根據(jù)方法參數(shù)信息(Object... args),經(jīng)由之前解析的參數(shù)注解信息可以得到一個(gè)最終的RequestBuilder,由這些信息就可以build出一個(gè)Request。
toRequest里面有句代碼是:
handlers[p].apply(requestBuilder, args[p]);
這里其實(shí)獲取得到的就是接口方法第p個(gè)參數(shù)解析出來的效果,舉個(gè)例子來說,比如,我們之前handlers[p]解析出來的是@Path的信息,那么handlers[p]就是一個(gè)ParameterHandler.Path類型的對(duì)象,而ParameterHandler.Path是ParameterHandler靜態(tài)內(nèi)部類,同時(shí)也是一個(gè)ParameterHandler子類:
static final class Path<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
private final boolean encoded;
Path(String name, Converter<T, String> valueConverter, boolean encoded) {
this.name = checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
@Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) {
throw new IllegalArgumentException(
"Path parameter \"" + name + "\" value must not be null.");
}
builder.addPathParam(name, valueConverter.convert(value), encoded);
}
}
所以,handlers[p].apply(requestBuilder, args[p])按官網(wǎng)的例子就變成了:
Path.apply(requestBuilder,String user)-->builder.addPathParam(”user", valueConverter.convert("user"), encoded);
而由我們前面的分析,此處的valueConverter默認(rèn)是ToStringConverter:
static final class ToStringConverter implements Converter<Object, String> {
static final ToStringConverter INSTANCE = new ToStringConverter();
@Override public String convert(Object value) {
return value.toString();
}
}
所以valueConverter.convert("user")-->"user".toString()=="user",所以最終返回的就是字符串"user",所以:
builder.addPathParam(”user", valueConverter.convert("user"), encoded)-->builder.addPathParam(”user", "user", encoded)。
對(duì)于@Path來說,肯定是將參數(shù)信息替換掉接口方法注解內(nèi)容相對(duì)路徑的{*}內(nèi)容,所以,builder.addPathParam就是實(shí)現(xiàn)這個(gè)功能的:
void addPathParam(String name, String value, boolean encoded) {
if (relativeUrl == null) {
// The relative URL is cleared when the first query parameter is set.
throw new AssertionError();
}
relativeUrl = relativeUrl.replace("{" + name + "}", canonicalizeForPath(value, encoded));
}
經(jīng)過以上步驟,就構(gòu)建出了一個(gè)HTTP請(qǐng)求。
最后,我們就可以用這個(gè)請(qǐng)求進(jìn)行真正的網(wǎng)絡(luò)發(fā)送call.enqueue,回顧上面OkHttpCall.enqueue方法,可以看到請(qǐng)求返回結(jié)果解析是在:
//OkHttpCall.enqueue片段代碼
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
可以看到,請(qǐng)求成功的時(shí)候,會(huì)調(diào)用parseResponse得到一個(gè)我們需要的Response<T>類型對(duì)象,具體解析方法如下:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
···
···
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
···
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
···
}
parseResponse就是對(duì)得到的rawResponse進(jìn)行處理判斷,最后交由到serviceMethod.toResponse做出最終的轉(zhuǎn)換。
/** Builds a method return value from an HTTP response body. */
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
可以看到這里就是用到了數(shù)據(jù)轉(zhuǎn)換器Converter<ResponseBody, R>將HTTP返回結(jié)果ResponseBody轉(zhuǎn)換成我們自己定義的類型R(默認(rèn)的Converter.Factory是BuiltInConverters,它所生產(chǎn)的Convert默認(rèn)不對(duì)ResponseBody進(jìn)行轉(zhuǎn)換)。
所以分析到了這里,Retrofit整體的流程我們也差不多整理完畢了。
最后進(jìn)行總結(jié)一下:
- 我們要是用
Retrofit進(jìn)行HTTP網(wǎng)絡(luò)請(qǐng)求的時(shí)候,首先要?jiǎng)?chuàng)建一個(gè)接口進(jìn)行HTTP動(dòng)作描述,之所以用接口是為了后面動(dòng)態(tài)創(chuàng)建一個(gè)對(duì)應(yīng)的接口代理類(java的動(dòng)態(tài)代理只能支持接口); - 接口描述創(chuàng)建完成后,通過建造者模式可以配置出一個(gè)
retrofit實(shí)例 - 由
retrofit的`create函數(shù)就可以創(chuàng)建出一個(gè)接口的動(dòng)態(tài)代理類 - 調(diào)用動(dòng)態(tài)代理類的接口方法時(shí),就會(huì)被動(dòng)態(tài)代理類攔截,攔截的主要原因就是為了隱式的創(chuàng)建出一個(gè)用于HTTP網(wǎng)絡(luò)請(qǐng)求的
Call對(duì)象,具體做了3件事:
?1. 解析接口注解內(nèi)容并保存,功能類為ServiceMethod。
?2. 創(chuàng)建一個(gè)OkHttpCall對(duì)象,OkHttpCall內(nèi)部持有okhttp3.Call實(shí)例。OkHttpCall的作用就是從ServiceMethod和當(dāng)前參數(shù)獲取得到一個(gè)Request,并通過OkHttpClient根據(jù)這個(gè)Request創(chuàng)建出一個(gè)okhttp3.Call對(duì)象。
?3. 最后從ServiceMethod中拿到一個(gè)可以處理接口方法返回類型的CallAdapter,由其adapt返回得到一個(gè)可以對(duì)HTTP請(qǐng)求結(jié)果進(jìn)行線程調(diào)度的retrofit2.Call對(duì)象(該Call對(duì)象是OkHttpCall的代理類)。