Retrofit源碼分析(結合LiveData)

    分析的源碼版本是: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進行的,相當於在其之上加了一層而已,只是這一層的封裝特別香。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章