Retrofit源码解析(一)源码流程

只是对网络请求做了一个封装,但是不做具体的网络请求,网络请求由okHttp做的。
讲解版本:

implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'

简单使用

interface IFreeService {
    @GET("api/personalMessage/get/{id}")
    fun updatePersonalMessage(
        @Path("id") personalId: String
    ): Call<ResponseBody>
}

var retrofit = Retrofit.Builder().baseUrl("")
    //设置数据解析器,创建含有Gson对象实例的GsonConverterFactory
    .addConverterFactory(GsonConverterFactory.create())
    .build()

// 将接口转换为实现类
var service = retrofit.create(IFreeService::class.java)
var respo = service.updatePersonalMessage("1")

// 同步请求
val request = respo.request()
// 异步请求
respo.enqueue(object : Callback<ResponseBody>{
    override fun onFailure(call: Call<ResponseBody>, t: Throwable) {
        TODO("Not yet implemented")
    }

    override fun onResponse(call: Call<ResponseBody>, response: Response<ResponseBody>) {
        TODO("Not yet implemented")
    }
})

整体流程

  • Build设计模式初始化Retrofit对象。根据不同平台初始化不同平台的对应继承子类。生成一个回调回UI线程的执行器,可以将执行结果返回至Ui线程内。生成一个网络请求适配器工厂。
  • 通过retrofit.create这个方法生成接口实现类,采用动态代理设计模式,把IFreeService的方法调用集中到了InvocationHandler.invoke,再构建了ServiceMethod,OKHttpCall,返回callAdapter.adapt的结果。使用Converter转化响应数据。
  • 借助Retrofit通过okHttp进行网络请求。通过toRequest方法,将retrofit的Request转换成okHttp的Request。对okHttp请求回来的数据通过Converter进行解析,调用到ServiceMethod#toResponse方法,将okhttp3.Response转化为retrofit2.Response。

核心

CallAdapter

callAdapter是由addCallAdapterFactory方法传入的,不传默认DefaultCallAdapterFactory。
DefaultCallAdapterFactory的adapter方法默认返回call。
作用是将包装对象转化为用户自定义对象。

Converter

Converter是由addConverterFactory方法传入的。
作用是将okhttp3.Response转化为retrofit2.Response。

Retrofit#create

public <T> T create(final Class<T> 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 {
            ...
            // 创建ServiceMethod对象,ServiceMethod主要负责解析它对应的method的各种参数,调用toRequest为OkHttp提供Request。
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            // OkHttpCall内部封装okhttp3.Call。
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            // 将包装对象转化为用户自定义对象
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
}

请求数据解析

ServiceMethod#Build()

Builder(Retrofit retrofit, Method method) {
  this.retrofit = retrofit;
  // 接口方法
  this.method = method;
  // 接口方法的注解,一般是请求方式
  this.methodAnnotations = method.getAnnotations();
  // 参数类型
  this.parameterTypes = method.getGenericParameterTypes();
  // 参数注解数组
  this.parameterAnnotationsArray = method.getParameterAnnotations();
}

ServiceMethod#build()

public ServiceMethod build() {
  callAdapter = createCallAdapter();
  responseType = callAdapter.responseType();
  ...
  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];
    ...
    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
   ...
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
  }
  ...
  return new ServiceMethod<>(this);
}

接口注解解析

parseHttpMethodAndPath

private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
  this.httpMethod = httpMethod;
  this.hasBody = hasBody;

  int question = value.indexOf('?');
  if (question != -1 && question < value.length() - 1) {
    String queryParams = value.substring(question + 1);
    Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
  }
  // 省略域名的URL
  this.relativeUrl = value;
  this.relativeUrlParamNames = parsePathParameters(value);
}

参数类型,注解解析

int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
    Type parameterType = parameterTypes[p];
    
    Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
    // 把参数类型,参数注解放在一起解析之后存储到了这个ParameterHandler<T>数组中,中间主要做了多种合法性校验,并根据注解的类型,生成不同的 ParameterHandler<T>子类
    // ParameterHandler抽象类,在apply方法中进行参数替换
    parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}

总结

Retrofit和OkHttp合作流程

Retrofit的OkHttpCall内部封装okhttp3.Call,调用enqueue方法时,内部实际调用的是okHttp的enqueue方法,okHttp使用的Request通过ServiceMethod的toRequest方法创建。回调回来的Response,通过parseResponse方法,使用Converter转化为自定义类型的Response。

Retrofit数据处理流程

交给了callAdapter以及converter去处理,callAdapter负责把okHttpCall转成用户自定义对象,converter负责把服务器返回的数据转成具体的实体类。

参考

Retrofit是如何工作的
Retrofit原理解析最简洁的思路

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。