分析的源碼版本是:retrofit 2.8.1
先看一個簡單實例,其中的Call用liveData適配。從這個demo開始一步步進行源碼分析
interface Api {
companion object {
fun getInstance(): Api {
return Retrofit.Builder()
.baseUrl("https://www.test.com/")
.client(OkHttpClient.Builder().build())
.addCallAdapterFactory(LiveDataCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(Api::class.java)
}
}
@GET("user/info")
fun getUserInfo(): LiveData<ApiResponse<UserVo>>
}
private fun loadData(){
val user = Api.getInstance().getUserInfo()
user.observe(this, Observer {
val user :UserVo? = it.data
})
}
一、流程分析
1.1 創建對象
從上面的demo圖中可以看出Api實例化的過程很簡單,重點在於最後兩步的build()創建Retrofit對象的過程和create(Api::class.java)創建Api實例的過程,前面配置的過程簡單,因此略過。
1.1.1 build()過程
/**
* 創建Retrofit實例對象
*/
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//設置callFactory,若沒有自己配置的話將採用默認的callFactory
//本例採用自定義的LiveDataCallAdapterFactory
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//根據平臺選擇執行者,Android這裏會選擇Android的執行者,默認是MainThreadExecutor
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 安全拷貝已設置的CallAdapter.Factory列表然後添加一個默認的CallAdapter.Factory
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<> (this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 拷貝已設置的和默認的Converter.Factory
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
//返回Retrofit實例,且爲了安全converterFactories和callAdapterFactories被設置爲不可變
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
可以看出build的過程是對設置的CallAdapterFactory和ConverterFactory做統一安全措施
1.1.2 create()過程
create()返回一個service動態代理(本例中是返回Api類的動態代理),當調用getUserInfo()方法時會進入到InvocationHandler的invoke()方法中。
public <T> T create(final Class<T> service) {
validateServiceInterface(service);//檢查service是否是有效的接口
//返回service的動態代理實例對象
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
//proxy指代理對象,method是代理對象的方法,args是方法的參數
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//重點行,調用對象方法
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
在本例中,service指的是傳入Api這個類,method就是getUserInfo()這個方法。其後通過動態代理創建類Api的實例化對象,重點在於最後的調用方法那行代碼
先看下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 = ServiceMethod.parseAnnotations(this, method); //重點行
serviceMethodCache.put(method, result);
}
}
return result;
}
這個方法就是返回一個ServiceMethod實例對象,跟進去看下ServiceMethod這個類的信息:
abstract class ServiceMethod<T> {
//解析註解
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//重點行①
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
//重點行②
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
可以看出ServiceMethod類是個抽象類,且非常簡單就只有一個解析註解的靜態方法parseAnnotations()和一個invoke()方法,根據方法解析它的註解,本例中就是解析getUserInfo()方法的get註解,返回的是HttpServiceMethod這個抽象類,它繼承自ServiceMethod,作用是將接口方法的調用調整爲HTTP調用。
上面有兩個重點行,重點行①是一個請求工廠類,這個類的作用是解析註解(包括方法註解及參數註解)封裝成okhttp3.Request請求(包括url字符串拼接,獲取其中的請求參數值等)。其中可以看到解析註解的關鍵方法:
重點行②的HttpServiceMethod.parseAnnotations()方法同樣是解析註解,進去看下它與重點行①的解析有什麼不同:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
... //省略
//創建CallAdapter實例
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
...//省略
//創建Converter實例
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter,
callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
可以看出, HttpServiceMethod.parseAnnotations()的作用主要就是根據方法註解創建CallAdapter和Converter的實例對象,也就是本例中的LiveDataCallAdapterFactory()和GsonConverterFactory()的實例對象。最後根據平臺版本返回不同的對CallAdapter的封裝類,最終會調用其中CallAdapter對象的的adapt()方法
回溯到1.1.2 create()過程的重點行:
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
這個invoke()實際上最終會調用HttpServiceMethod類實例的invoke()方法:
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory,
responseConverter);
return adapt(call, args);
}
可以看到這裏實例化了一個OkHttpCall對象,傳入了請求參數,調用了adapt()方法,實際上最後調用的是上面說的CallAdapter對象的的adapt()方法,其中會調用Call.enque()或者調用CAll.execute()方法發起網絡請求,由於我們是自定義的LiveDataCallAdapter,所以會調用LiveDataCallAdapter對象的adapt()方法,簡單來說,Create()過程做的主要工作就是解析註解封裝成request請求和實例化callAdapter與responseConverter的過程。
1.2 網絡請求
進入到LiveDataCallAdapter類中看看,會看到adapt()方法中實際上調用了call.enqueue()發起了異步網絡請求,onResponse()中獲得請求的返回信息後封裝成LiveData數據返回給調用方
//將Retrofit的Call對象適配成LiveData
class LiveDataCallAdapter<T>(private val responseType: Type) : CallAdapter<T, LiveData<T>> {
override fun adapt(call: Call<T>): LiveData<T> {
return object : LiveData<T>() {
private val started = AtomicBoolean(false)
override fun onActive() {
super.onActive()
if (started.compareAndSet(false, true)) {//確保執行一次
call.enqueue(object : Callback<T> {
override fun onFailure(call: Call<T>, t: Throwable) {
val value = ApiResponse<T>(null, -1, t.message ?: "") as T
postValue(value)
}
override fun onResponse(call: Call<T>, response: Response<T>) {
postValue(response.body())
}
})
}
}
}
}
override fun responseType() = responseType
}
private fun loadData(){
val user = Api.getInstance().getUserInfo()
user.observe(this, Observer {
val user :UserVo? = it.data
})
}
然後通知liveData的觀察者更新數據,最終在observe方法中拿到數據。至此一個網絡請求流程就走通了。
二、總結
retrofit主要就是對OKhttp的封裝,封裝的重點在於對註解的豐富解析,對CallAdapter的擴展支持,對Converter的豐富支持。最終封裝成簡單易用的網絡框架,實際上的網絡請求還是通過okhttp進行的,相當於在其之上加了一層而已,只是這一層的封裝特別香。