Retrofit這個(gè)開(kāi)源庫(kù)出來(lái)也有一定年頭了,記得之前還是在V1.0的版本的時(shí)候,之前在三月份也寫過(guò)一個(gè)Retrofit的使用簡(jiǎn)析,那會(huì)兒正是1.0向2.0過(guò)渡的時(shí)候,所以新版本老版本對(duì)比了一下!時(shí)至今日,相關(guān)文章已經(jīng)層出不窮了,今天主要是打開(kāi)它的源碼,了解一些細(xì)節(jié)的問(wèn)題!
準(zhǔn)備工作
基于版本:
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0'
相關(guān)問(wèn)題:
1、Retrofit是使用注解確定對(duì)應(yīng)的請(qǐng)求方式和參數(shù)的,那么具體的url是怎么產(chǎn)生出來(lái)的的呢?
2、我們定義的是一個(gè)接口,那么Retrofit又是怎么生成對(duì)應(yīng)的實(shí)現(xiàn)類的呢?
3、網(wǎng)絡(luò)請(qǐng)求V2.0開(kāi)始統(tǒng)一使用OkHttp了,那么異步回調(diào)到主線程是如何實(shí)現(xiàn)的?
4、同一個(gè)方法,支持Call<T>
的返回類型,又可以支持Observable<T>
的返回類型,這個(gè)又是如何實(shí)現(xiàn)的?
5、同一個(gè)方法,支持不同的轉(zhuǎn)換(Gson
、Jackson
、Moshi
、FastJson
等等),這個(gè)又是如何實(shí)現(xiàn)的呢?
帶著這些問(wèn)題,我們可以更好的進(jìn)行相關(guān)的源碼分析
第一部分 Retrofit && ServiceMethod的創(chuàng)建
從Retrofit的構(gòu)建方法開(kāi)始說(shuō)起
new Retrofit.Builder()
.baseUrl("http://10.0.60.115:60321/1.0/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
return chain.proceed(RequestUtils.createLoginJsonRequest(chain.request()));
}
})
.addNetworkInterceptor(
new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.HEADERS))
.build())
.build()
.create(LoginApi.class);
這里就是顯而易見(jiàn)的builder模,通過(guò)Builder去構(gòu)建我們需要的一些必要數(shù)據(jù)(比如說(shuō)baseUrl,callAdapter,Conver等等),接下來(lái)看看Builder里面具體做了些什么!!
調(diào)用Retrofit內(nèi)部的Builder的空參數(shù)構(gòu)造方法!:
public Builder() {
this(Platform.get());
}
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());
}
在這里,又去調(diào)用了Platform.get()
初始化了一個(gè)Platform
,并把默認(rèn)的轉(zhuǎn)換器BuiltInConverters
初始化并加入了集合中!!
那么問(wèn)題來(lái)了,這個(gè)Platform
是何方神圣,具體有撒作用??順藤摸瓜,這里開(kāi)始介紹內(nèi)部的第一個(gè)神秘嘉賓!!
Platform 初始化
private static final Platform PLATFORM = findPlatform();//初始化`Platform`的靜態(tài)方法
Platform
字面意思就是平臺(tái)啦,所以Platform
相當(dāng)于一個(gè)抽象類,這個(gè)類里面有對(duì)應(yīng)的實(shí)現(xiàn)類:Android iOS Java 8對(duì)應(yīng)的是各種具體平臺(tái)。
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();
}
可以看到,在調(diào)用findPlatform()
方法之后就回去判斷初始化對(duì)應(yīng)的具體平臺(tái),具體的實(shí)現(xiàn)類就是上面說(shuō)到的三個(gè),Android Java iOS,你沒(méi)有看錯(cuò),還有iOS的(這里是用的Swift
),嘖嘖。。
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);
}
}
}
各個(gè)不同的平臺(tái)其實(shí)就是根據(jù)不同的環(huán)境初始化不同的MainThreadExecutor
,像上面的Android平臺(tái)當(dāng)然就是獲取主線程的Handler
!!這里可以看到,在初始化Platform
之后,通過(guò)Platform
得到的ExecutorCallAdapterFactory
的工廠的Executor
其實(shí)就是運(yùn)行在主線程的Executor
!
Builder
的默認(rèn)構(gòu)造函數(shù)基本上講完了!其實(shí)就是通過(guò)對(duì)應(yīng)的平臺(tái)構(gòu)建了一個(gè)具體的Platform
,通過(guò)這個(gè)Platform
構(gòu)建出了對(duì)應(yīng)平臺(tái)的主線程隊(duì)列的線程池,方便后面的方法回調(diào)到主線程中!這里基本上也可以回答第三個(gè)問(wèn)題了,異步怎么回調(diào)到主線程的!
添加baseUrl
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
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;
}
這里沒(méi)撒說(shuō)的,就是檢測(cè)一下url的格式,然后完成賦值!
addConverterFactory && addCallAdapterFactory
/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
/**
* Add a call adapter factory for supporting service method return types other than {@link
* Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
這里忍不住必須說(shuō)兩句了,這兩個(gè)方法套路是完全一樣——適配器模式,CallAdapter
是請(qǐng)求Call
對(duì)應(yīng)的適配器,CallAdapter.Factory
是創(chuàng)建對(duì)應(yīng)CallAdapter
的抽象工廠!! Converter
是解析的轉(zhuǎn)換器,這里提供了三種轉(zhuǎn)換場(chǎng)景,responseBodyConverter
、requestBodyConverter
、stringConverter
。Converter.Factory
則是Convert
的抽象工廠,這樣利于我們的后期擴(kuò)展,比如說(shuō)外國(guó)人肯定沒(méi)有寫對(duì)應(yīng)FastJson
的Covert
,但是它提供了工廠的嘛,我們繼承這個(gè)抽象工廠,實(shí)現(xiàn)出來(lái)就好了!!
RxJavaCallAdapterFactory
在RxJavaCallAdapterFactory這個(gè)工廠中,又定義了兩種 ,一種是SimpleCallAdapter
另外一種是ResultCallAdapter
,
//SimpleCallAdapter
@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;
}
//ResultCallAdapter
@Override public <R> Observable<Result<R>> adapt(Call<R> call) {
Observable<Result<R>> observable = Observable.create(new CallOnSubscribe<>(call)) //
.map(new Func1<Response<R>, Result<R>>() {
@Override public Result<R> call(Response<R> response) {
return Result.response(response);
}
}).onErrorReturn(new Func1<Throwable, Result<R>>() {
@Override public Result<R> call(Throwable throwable) {
return Result.error(throwable);
}
});
if (scheduler != null) {
return observable.subscribeOn(scheduler);
}
return observable;
}
通俗的說(shuō)其實(shí)就是根據(jù)返回值類型判斷返回的Observable
是否需要處理一下對(duì)應(yīng)的Response
!!使用flatMap()
將其包裝為一個(gè)新的Observable
返回!!
Retrofit在創(chuàng)建的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);
//添加完之后再添加一個(gè)defaultCallAdapterFactory
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);
}
//這個(gè)方法是上面提到的platform里面的方法,通過(guò)這個(gè)方法,將主線程的線程池和ExecutorCallAdapterFactory關(guān)聯(lián)起來(lái)了!!
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
到這里,Builder的創(chuàng)建過(guò)程分析完畢,總結(jié)起來(lái)就是創(chuàng)建出具體的Platform
,通過(guò)具體的Platform
創(chuàng)建出主線程的線程池,然后構(gòu)建出默認(rèn)的ExecutorCallAdapterFactory
,另外就是添加對(duì)應(yīng)的CallAdapter.Factory
(比如說(shuō)RxJavaCallAdapterFactory 等)和Converter.Factory
!
生成接口的代理對(duì)象
build()
方法創(chuàng)建對(duì)應(yīng)的Retrofit
之后就是create(Class<T> service)
的方法,這里就是生成對(duì)應(yīng)的接口的代理類的方法!!
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
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);
}
});
}
可以看到,在調(diào)用create()
方法之后,是通過(guò)Proxy
生成對(duì)應(yīng)的動(dòng)態(tài)代理!這里就很好說(shuō)咯,在對(duì)應(yīng)的invoke()
的方法中完成具體的請(qǐng)求!
如果Java
的動(dòng)態(tài)代理不清楚或者已經(jīng)忘記了的親們,這里先簡(jiǎn)單腦補(bǔ)一下,代理的對(duì)應(yīng)方法最后都會(huì)交給InvocationHandler
這個(gè)類,并通過(guò)invoke(Object proxy, Method method, Object... args)
的方法去執(zhí)行相關(guān)的邏輯,這里的Method是對(duì)應(yīng)具體方法的信息摘要,反射對(duì)象,里面包含了method的名稱,參數(shù)類型,包括注解那些反正是應(yīng)有盡有啦!這個(gè)args就是具體的方法參數(shù)了!
接下來(lái)就要注意啦,在創(chuàng)建好了Retrofit之后,在生成動(dòng)態(tài)代理之后,咱們的請(qǐng)求方法還沒(méi)有構(gòu)建出來(lái)呢!所以呢,接下來(lái)肯定就是構(gòu)建相關(guān)的請(qǐng)求方法咯!!
但是明確看到,在返回動(dòng)態(tài)代理之前我們看到這里有一個(gè)判斷validateEagerly
,而且對(duì)應(yīng)的Builder 對(duì)外提供了一個(gè)設(shè)置的方法!
/**
* When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate
* the configuration of all methods in the supplied interface.
*/
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
這個(gè)方法到底是來(lái)做撒的呢?英語(yǔ)好的應(yīng)該都看明白了!我先繞個(gè)關(guān)子不講了!!
直接到代理的invoke()
方法中,這里有兩個(gè)條件判斷,第一個(gè)是判斷返回的類型如果就是Object,那就撒都不搞了,直接執(zhí)行!
第二個(gè)判斷如果這個(gè)方法是Default的,這個(gè)主要是針對(duì)java8來(lái)說(shuō)得呢!所以重點(diǎn)還是要跳過(guò)到最下面!
ServiceMethod serviceMethod = loadServiceMethod(method);
ServiceMethod的創(chuàng)建
繼上面說(shuō)過(guò)的Platform
之后,ServiceMethod
是我們開(kāi)始講解的第二個(gè)類了!這里開(kāi)始創(chuàng)建出對(duì)應(yīng)的ServiceMethod
對(duì)象,到這個(gè)方法里面具體看看!
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;
}
舉個(gè)例子,比如說(shuō)我們?cè)贚oginApi這個(gè)接口里面定義了兩個(gè)方法:
@POST("users")//https://api.bmob.cn/1/ 注冊(cè)用戶
Call<UserBean> registerUser( @Body UserBean bean);
@GET("getUserInfo")//https://api.bmob.cn/1/用戶登陸
Observable<Result<UserBean>> login(@QueryMap Map<String,String> map);
那么當(dāng)我們執(zhí)行login()
方法的時(shí)候,就會(huì)創(chuàng)建Retrofit
,并且創(chuàng)建這個(gè)LoginApi
的動(dòng)態(tài)代理,然后調(diào)用login()
方法,那么這里loadServiceMethod(Method method)
中的method方法就是login()
這個(gè)方法的對(duì)象。然后通過(guò)ServiceMethod.Builder
去構(gòu)建這個(gè)具體的ServiceMethod
。
//ServiceMethod.Builder的構(gòu)造方法
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();//獲取方法的對(duì)應(yīng)注解@retrofit2.http.POST(value=files/{fileName})
this.parameterTypes = method.getGenericParameterTypes();//獲取方法參數(shù)的類型
this.parameterAnnotationsArray = method.getParameterAnnotations();//獲取方法參數(shù)的注解
}
接下來(lái)重點(diǎn)看看ServiceMethod.Builder.builder()
的構(gòu)建過(guò)程!這里算是Retrofit
里面比較重要的一塊了吧,因?yàn)樗_(kāi)始拼接url、確定返回類型、明確CallAdapter
和responseConverte
!
public ServiceMethod build() {
//1、獲取對(duì)應(yīng)的callAdapter
callAdapter = createCallAdapter();
//2、獲取對(duì)應(yīng)的response的類型
responseType = callAdapter.responseType();
//3、創(chuàng)建response的轉(zhuǎn)換器
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
//4、根據(jù)方法的注解(GET POST)開(kāi)始具體的解析
parseMethodAnnotation(annotation);
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
..........
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
........
//5、解析對(duì)應(yīng)的方法參數(shù)注解
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
-
1、獲取對(duì)應(yīng)的callAdapter
private CallAdapter<?> createCallAdapter() { //獲取返回值的Type,后面會(huì)用到 Type returnType = method.getGenericReturnType(); ...... Annotation[] annotations = method.getAnnotations(); try { //調(diào)用retrofit的方法 return 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); } } //callAdapter()方法最終調(diào)用nextCallAdapter()來(lái)確定具體的callAdapter public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { .... int start = adapterFactories.indexOf(skipPast) + 1; for (int i = start, count = adapterFactories.size(); i < count; i++) { //get是抽象方法,由具體的factory去實(shí)現(xiàn) CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } ..... }
前面在說(shuō)Retrofit的初始化的時(shí)候,就說(shuō)了默認(rèn)會(huì)添加ExecutorCallAdapterFactory
,如果我們添加了RxJava支持了添加一個(gè)RxJavaCallAdapterFactory
的話,那我們這里就有兩個(gè)CallAdapter
了,那么Retrofit是如何明確到底應(yīng)該使用哪個(gè)Adapter的呢?(問(wèn)題四)相關(guān)的答案都在get()
的方法中!我們可以看看這兩個(gè)Factory里面具體的get方法是怎么處理的!
//ExecutorCallAdapterFactory中
@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//可以處理Call的返回類型
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
//RxJavaCallAdapterFactory中
@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);
//可以處理 Observable rx.Single rx.Completable的類型
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
....
}
答案很是清晰明了啊,不同的adapter
在get()中處理不同的邏輯!
- 2、獲取對(duì)應(yīng)的response的類型
這里的response其實(shí)就是之前的獲取到的returnType在獲取到的里面的具體類型,比如說(shuō)returnType是Call<UserInfo>,那么這里就獲取到對(duì)應(yīng)的UserInfo,相關(guān)方法封裝放在Utils這個(gè)工具類中滴!!
-
3、創(chuàng)建response的轉(zhuǎn)換器
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); } } public <T> Converter<ResponseBody, T> nextResponseBodyConverter(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; } } .... }
這里其實(shí)和前面的創(chuàng)建CallAdapter
的原理是一致的!最后調(diào)用Retrofit
的responseBodyConverter()
方法,最后調(diào)用nextResponseBodyConverter()
的方法,這里這個(gè)行為模式就是傳說(shuō)中的責(zé)任鏈模式吧!如果添加了多個(gè),json解析的是要放最后面的,因?yàn)樗莵?lái)者不拒的了!!
- 4、根據(jù)方法的注解(GET POST)開(kāi)始具體的解析
到這里就要開(kāi)始解析方法上的對(duì)應(yīng)注解了!
比如說(shuō)下面這個(gè)Get請(qǐng)求:
@GET("news/before/{date}")
Observable<DailyStories> getBeforeDailyStories(@Path("date") String date);
在通過(guò)parseMethodAnnotation()
方法之后,會(huì)繼續(xù)執(zhí)行parseHttpMethodAndPath("GET", ((GET) annotation).value(), false)
的方法!
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;
}
}
在parseHttpMethodAndPath()
中進(jìn)行httpMethod、hasBody、relativeUrl、relativeUrlParamNames的賦值!
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
...
this.httpMethod = httpMethod;//GET
this.hasBody = hasBody;//false
...
this.relativeUrl = value;//news/before/{date}
this.relativeUrlParamNames = parsePathParameters(value);
}
最后一個(gè)parsePathParameters()
需要我們著重看一下,到這就要進(jìn)行相關(guān){date}的替換了!
static Set<String> parsePathParameters(String path) {
//static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
Matcher m = PARAM_URL_REGEX.matcher(path);
Set<String> patterns = new LinkedHashSet<>();
while (m.find()) {
patterns.add(m.group(1));
}
return patterns;
}
因?yàn)?code>{date}這一塊是需要替換成方法參數(shù)里面對(duì)應(yīng)的那個(gè)具體值的,這里通過(guò)relativeUrlParamNames()
的方法,先將{date}取出存入了set集合中!!方便后面根據(jù)方法上對(duì)應(yīng)的參數(shù)進(jìn)行替換!!
解析對(duì)應(yīng)的方法參數(shù)
接下來(lái)就是解析方法對(duì)應(yīng)的參數(shù)的注解了:
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);
}
這里出現(xiàn)了一個(gè)新的類ParameterHandler,這也是第三個(gè)需要介紹的類了!
ParameterHandler
如圖所示,ParameterHandler
它是一個(gè)抽象類,有這么多具體的實(shí)現(xiàn)小弟來(lái)管理某個(gè)具體參數(shù)!里面還有一個(gè)抽象方法apply()
需要每個(gè)子類去實(shí)現(xiàn)的。這個(gè)方法將在后面將具體參數(shù)封裝到RequestBuilder
里面。在上面舉例的方法:
//parameterCount=1,parameterTypes[0]=String.class
getBeforeDailyStories(@Path("date") String date)
所以最后就是執(zhí)行parseParameter(0,String,Path)
,并且返回的就是ParameterHandler
的對(duì)象!接下來(lái)具體看內(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;
}
這里接著去調(diào)用parseParameterAnnotation()
的方法,這也是ParameterHandler
具體創(chuàng)建的方法!
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
...
} else if (annotation instanceof Path) {
...
gotPath = true;
Path path = (Path) annotation;
String name = path.value();
validatePathName(p, name);
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
//創(chuàng)建出對(duì)應(yīng)的PathParameterHandler!!
return new ParameterHandler.Path<>(name, converter, path.encoded());
} .......
return null; // Not a Retrofit annotation.
}
這里會(huì)根據(jù)不同的類型創(chuàng)建不同的Convert
,比如說(shuō)解析Path就是使用StringConver,并且會(huì)先調(diào)用validatePathName()
的方法去判斷之前的Set集合里面是否有這個(gè)值,如果有,那么就創(chuàng)建出一個(gè)ParameterHandler.Path
的對(duì)象!
同理解析Body
的時(shí)候就會(huì)去調(diào)用nextRequestBodyConverter()
的方法最終確認(rèn)對(duì)應(yīng)的Convert
,就這樣,最后創(chuàng)建出了ParameterHandler.Body
這個(gè)具體的ParameterHandler
對(duì)象!并且相關(guān)方法的參數(shù)的注解也解析出來(lái)并封裝到了parameterHandlers
數(shù)組中!
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;
}
到了這里,ServiceMethod
的初始化完成,那么每次都去辛辛苦苦的構(gòu)建這些注解和參數(shù)是不是太累了?!所以必須把它緩存起來(lái)咯!這里也是上面提出的那個(gè)validateEagerly
和eagerlyValidateMethods()
問(wèn)題的答案:如果我們需要盡快構(gòu)建出每個(gè)方法的ServiceMethod,那么就將validateEagerly
設(shè)置為true就好了!
第二部分 HTTP請(qǐng)求 響應(yīng) 轉(zhuǎn)換
經(jīng)過(guò)上面一系列的準(zhǔn)備工作,接下來(lái)就是開(kāi)始相關(guān)的網(wǎng)絡(luò)請(qǐng)求了!回到Retrofit
的代理方法中:
//上面已經(jīng)創(chuàng)建好對(duì)應(yīng)的ServiceMethod了!
ServiceMethod serviceMethod = loadServiceMethod(method);
//初始化OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//執(zhí)行具體的call
return serviceMethod.callAdapter.adapt(okHttpCall);
OkHttpCall
沒(méi)有記錯(cuò)的話,OkHttpCall
是我們要介紹的第四個(gè)對(duì)象了!也是比較重要的一個(gè)對(duì)象了,OkHttpCall
實(shí)現(xiàn)了 Call
接口,內(nèi)部持有okhttp3.Call
的引用,所以可以理解為它是OkHttp
的Call
的代理對(duì)象!
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
這里構(gòu)建出一個(gè)具體的OkHttpCall
的對(duì)象!然后調(diào)用了serviceMethod.callAdapter.adapt(okHttpCall)
這個(gè)方法,接下來(lái)著重分析這個(gè)方法做了些什么操作!
adapt()
是CallAdapter
里面的抽象方法,由具體的子類實(shí)現(xiàn)!如果我們返回的是Call
類型的,那么由上面第一部分分析,ServiceMethod
這里就是是用的ExecutorCallAdapterFactory
!那么到ExecutorCallAdapterFactory
中看看具體的實(shí)現(xiàn)邏輯!!
@Override
public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
這里又返回了一個(gè)ExecutorCallbackCall
的對(duì)象!這里的callbackExecutor
就是在講初始化Platform
創(chuàng)建的!
當(dāng)我們調(diào)用具體的方法時(shí):
login.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
}
});
其實(shí)就是調(diào)用ExecutorCallbackCall
里面的對(duì)應(yīng)方法咯!
@Override
public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("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);
}
});
}
});
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
通過(guò)上面的方法就可以完全明白為什么enqueue
的方法都是在主線程上的了!!
這里的delegate
就是之前傳入的OkHttpCall
對(duì)象,所以這里又會(huì)去執(zhí)行OkHttpCall
里面的enqueue()
方法,繞了半天,終于又回到了OkHttpCall
里面了!
@Override
public void enqueue(final Callback<T> callback) {
....
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
//如果call沒(méi)有創(chuàng)建那么就去創(chuàng)建!
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
....
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();
}
}
});
}
這個(gè)方法有點(diǎn)兒長(zhǎng),主要是判斷有木有創(chuàng)建okhttp3.Call
,沒(méi)有就去創(chuàng)建,創(chuàng)建了就調(diào)用call的call.enqueue()
方法,最后再將結(jié)果通過(guò)傳入的Callback
回調(diào)出去!
RequestBuilder
先說(shuō)okhttp3.Call
的創(chuàng)建:
call = rawCall = createRawCall();
這里調(diào)用了OkHttpCall
里面的createRawCall()
方法:
private okhttp3.Call createRawCall() throws IOException {
//首先創(chuàng)建出okhttp3.Request
Request request = serviceMethod.toRequest(args);
//通過(guò)request構(gòu)建 okhttp3.Call
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
那么從這里開(kāi)始,這些任務(wù)又回到了ServiceMethod
這個(gè)類中了!所以說(shuō)ServiceMethod
完全服務(wù)于Http請(qǐng)求響應(yīng)的相關(guān)過(guò)程!
/** Builds an HTTP request from method arguments. */
Request toRequest(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.
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();
}
它構(gòu)建出一個(gè)RequestBuilder
的類,這也是第五個(gè)需要講解的類了!看名字都知道它就是用來(lái)構(gòu)建Request
的Builder
啦!,構(gòu)建出Builder之后,注意這次是帶上具體的參數(shù)過(guò)來(lái)的,所以它會(huì)進(jìn)行參數(shù)的封裝,構(gòu)建出最終要去請(qǐng)求的url!!之前有說(shuō)過(guò)對(duì)應(yīng)的每個(gè)參數(shù)注解已經(jīng)封裝到ParameterHandler
這個(gè)類中了,這里就需要遍歷parameterHandlers
這個(gè)數(shù)組,完成對(duì)每一個(gè)參數(shù)的具體賦值,賦值其實(shí)也很簡(jiǎn)單,就是依次調(diào)用各個(gè)ParameterHandler
的apply(requestBuilder, arg)
方法,apply()
方法其實(shí)就是調(diào)用之前構(gòu)建好的Convert
將對(duì)應(yīng)的參數(shù)(arg)解析成Request里面具體需要的對(duì)象!里面StringConvert
居多!比如之前說(shuō)到的@Body
的情況(第一部分的結(jié)尾)!,因?yàn)?code>Body你也可以傳入一個(gè)Bean
對(duì)象,所以不一定使用的是StringConvert
,這里它會(huì)通過(guò)nextRequestBodyConverter()
遍歷尋找合適Convert。
比如說(shuō)調(diào)用了GsonRequestBodyConverter
中的convert
方法完成相關(guān)解析:
@Override
public RequestBody convert(T value) throws IOException {
Buffer buffer = new Buffer();
Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
JsonWriter jsonWriter = gson.newJsonWriter(writer);
adapter.write(jsonWriter, value);
jsonWriter.close();
return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
}
接著就是調(diào)用requestBuilder.build()
的方法了!
Request build() {
//1.構(gòu)建HttpUrl
HttpUrl url;
HttpUrl.Builder urlBuilder = this.urlBuilder;
if (urlBuilder != null) {
url = urlBuilder.build();
} else {
// No query parameters triggered builder creation, just combine the relative URL and base URL.
url = baseUrl.resolve(relativeUrl);
if (url == null) {
throw new IllegalArgumentException(
"Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
}
}
2.構(gòu)建RequestBody
RequestBody body = this.body;
if (body == null) {
// Try to pull from one of the builders.
if (formBuilder != null) {
body = formBuilder.build();
} else if (multipartBuilder != null) {
body = multipartBuilder.build();
} else if (hasBody) {
// Body is absent, make an empty body.
body = RequestBody.create(null, new byte[0]);
}
}
MediaType contentType = this.contentType;
if (contentType != null) {
if (body != null) {
body = new ContentTypeOverridingRequestBody(body, contentType);
} else {
requestBuilder.addHeader("Content-Type", contentType.toString());
}
}
return requestBuilder
.url(url)
.method(method, body)
.build();
}
到這里Request終于是構(gòu)建好了!接下來(lái)是真正的去創(chuàng)建okhttp3.Call
了!
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
這里其實(shí)最終使用的是Retrofit
里面構(gòu)建的okhttp3.Call.Factory
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Response
最后終于到結(jié)果的位置了,這個(gè)Response也是我們要介紹的第六個(gè)對(duì)象了!它算是okhttp.Response
的一個(gè)裝飾類吧!也是最后返回給調(diào)用者使用的類!
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;
}
}
無(wú)論是同步或者異步的方法,最后總會(huì)通過(guò)parseResponse()
的方法將okhttp3.Response
包裝為Response
對(duì)象返回!!而具體的解析又會(huì)交給ServiceMethod
里面的的toResponse()
去處理!!
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
其實(shí)就是調(diào)用之前確認(rèn)好的responseConverter
去解析對(duì)應(yīng)的Body
!
到這里,http請(qǐng)求完成,結(jié)果也被封裝為指定的對(duì)象返回了!
總結(jié)
1、Call
(接口):向服務(wù)器發(fā)送請(qǐng)求并返回響應(yīng)的調(diào)用;
2、CallAdapter
(接口):Call
的適配器,將Call適配為不同的類型返回(Call、Observable);
3、CallBack
(接口):顧名思義Call的回調(diào),Call
執(zhí)行時(shí)的回調(diào);
4、Converter
(接口):數(shù)據(jù)轉(zhuǎn)換器,將一個(gè)對(duì)象轉(zhuǎn)化另外一個(gè)對(duì)象;
5、CallAdapter.Factory
(接口):CallAdapter
的工廠,通過(guò)get()
方法獲取CallAdapter,使用adapt()
執(zhí)行對(duì)應(yīng)的Call
請(qǐng)求;
6、Converter.Factory
(抽象類) : 數(shù)據(jù)轉(zhuǎn)換器Converter
的工廠;
-
responseBodyConverter
:將ResponseBody轉(zhuǎn)換為具體的對(duì)象。 -
requestBodyConverter
: 將對(duì)應(yīng)的Body
,Part
和PartMap
注解轉(zhuǎn)換為RequestBody(OkHttp3)
,以便http請(qǐng)求的時(shí)候使用。 -
StringConverter
:將Field
,FieldMap
值,Header
,Path
,Query
,和QueryMap
值轉(zhuǎn)化為String
,以便http請(qǐng)求的時(shí)候使用。
7、ParameterHandler
: 方法參數(shù)的處理類;
8、ServiceMethod
:請(qǐng)求方法的生成處理類,用于確定CallAdapter
、ResponseConverter
,生成具體的請(qǐng)求Request
,解析對(duì)應(yīng)的Response
數(shù)據(jù),算是一個(gè)灰常重要的類了;
9、Platform
:確認(rèn)不同運(yùn)行環(huán)境的類;
10、OkHttpCall
:實(shí)現(xiàn)Call
接口,是okhttp3.Call
的代理類,獲取傳入的Call,通過(guò)Retrofit.callFactory
執(zhí)行Call
請(qǐng)求,獲取數(shù)據(jù)并使用ResponseConverter
進(jìn)行解析;
再回到之前說(shuō)的那些問(wèn)題上:
1、Retrofit是使用注解確定對(duì)應(yīng)的請(qǐng)求方式和參數(shù)的,那么具體的url是怎么產(chǎn)生出來(lái)的的呢?
(ServiceMethod里面的相關(guān)處理)
2、我們定義的是一個(gè)接口,那么Retrofit又是怎么生成對(duì)應(yīng)的實(shí)現(xiàn)類的呢?
(動(dòng)態(tài)代理)
3、網(wǎng)絡(luò)請(qǐng)求V2.0開(kāi)始統(tǒng)一使用OkHttp了,那么異步回調(diào)到主線程是如何實(shí)現(xiàn)的?
(MainThreadExecutor)
4、同一個(gè)方法,支持Call<T>的返回類型,又可以支持Observable<T>
的返回類型,這個(gè)又是如何實(shí)現(xiàn)的?
(確定對(duì)應(yīng)CallAdapter
!)
5、同一個(gè)方法,支持不同的轉(zhuǎn)換(Gson、Jackson、Moshi、FastJson等等),這個(gè)又是如何實(shí)現(xiàn)的呢?
(確定對(duì)應(yīng)的Convert!)
搞了這么久,學(xué)習(xí)到什么呢?從一開(kāi)始的一臉懵逼到最后的暗自竊喜,這也算是一種進(jìn)步吧!其中不得不提的是各種設(shè)計(jì)模式的使用,模塊間解耦和擴(kuò)展的思想!創(chuàng)建型的抽象工廠模式、Builder模式;結(jié)構(gòu)性的代理模式、adapter模式、裝飾者模式;行為性的責(zé)任鏈模式等等。。
---- Edit By Joe ----