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进行的,相当于在其之上加了一层而已,只是这一层的封装特别香。

 

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