【拆轮子系列】Retrofit 源码的简要分析

现在的项目中用到了 Retrofit 用于网络请求,所以花了一些时间分析了它的源码,现在做一个简要的分析。

总体来看,Retrofit 使用了动态代理模式,它不是最终请求网络,真正请求网络的是 OkHttp. 这里,不做具体分析,我计划在下一篇再分析。

先看看它的整体流程
Retrofit 整体流程

我们先看正常的使用 Retrofit, 然后再结合上图分析。

    Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(sOkHttpClient)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .build();

这是正常的配置

1. 在 Retrofit.Buidler() 中的源码

 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) {
        // 根据 platform, 选择不同的 CallbackExecutor
        // 这里是 platform 是 Android , 返回的是 MainThreadExecutor;
        //  MainThreadExecutor 类,内部是通过 Handler 将 Runnable post 回主线程执行
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      // adaperFactories 是用来在存放 CallAdapterFactory, 例如使用 RxJavaCallAdapterFactory, 也会添加进来
      List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
      //defaultCallAdapterFactory 是 ExecutorCallAdapterFactory,其中 MainThreadExcutor 作为参数构造
      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);
    }

具体的分析看注释;

2. Retrofit.create()

在该方法中使用了动态代理模式,见 代理模式和动态代理模式

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    // 动态代理, 返回一个 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);
            }

            // 默认是 false
            if (platform.isDefaultMethod(method)) {
                return platform.invokeDefaultMethod(method, service, proxy, 
                                                                      args);
            }

            // ServiceMethod 调用接口的方法,转变成一个 Http Call
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);

            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            // serviceMethod.callAdapter 返回是 默认ExecutorCallAdapterFactory
            // &ExecutorCallbackCall
            // 如果添加了 RxJavaCallAdapter, 返回的是 RxJavaCallAdapter
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

3. ServiceMethod.build()

该方法主要做了三点

  • 取出在 Retrofit.build 中的 CallAdapter, 例如上面配置的是 RxJavaCallAdapterFactory, 则得到的是 RxJavaCallAdapter;
  • 取出 Retrofit.build 中的 responseConverter, 例如上面配置的是 GsonConverterFactory, 则得到 GsonResponseBodyConverter.
  • 解析注解方法
public ServiceMethod build() {
      // 创建 CallAdapter, 其实是返回 Retrofit 中的 callAdapter,
      // ExecutorCallAdapterFactory$ExecutorCallbackCall
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      // 返回 Retrofit.responseBodyConverter(...), 其实是从 converterFactories 中取出 ResponseBodyConverter
      //  例如,如果配置了 GsonResponseBodyConverter, 则返回.
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        // 解析注解方法,
        //@GET("group/{id}/users")
        //Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
        // 中的 @GET("group/{id}/users")
        parseMethodAnnotation(annotation);
      }

    // 省略后面
    .... 
}

Retrofit 的执行

call 的执行有同步方法和异步方法
同步 call.execute()
异步 call.enqueue(Callback callback);
这里以同步为例
执行部分

1. OkHttpCall.execute

// 同步执行
  @Override
  public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
     // 省略
    ...
      call = rawCall;
      if (call == null) {
        try {
          // 创建 Call
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }

    // 发起请求,并解析返回结果
    // 这里的 call 是 OkHttp 中的 RealCall
    return parseResponse(call.execute());
  }

2. OkHttpCall.createRawCall

  private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    // 返回的是 RealCall
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

3. OkHttCall.parseResponse

Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();
    // 省略
   ....

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      // T 是想要的结果,例如  Call<List<Repo>> listRepos(@Path("user")
      // String user); 中的 List<Repo>
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
     // 省略
     ...
    }
  }

3. ServiceMethod.toResponse

 /** Builds a method return value from an HTTP response body. */
  R toResponse(ResponseBody body) throws IOException {
    // responseConverter 是 Retrofit 中配置的 Conveter
    return responseConverter.convert(body);
  }

上面例子配置的 Conveter 是 GsonConverter, 所以,这里的 resonseConverter 是 GsonResponseConverter.

如果我们将 Http 返回的结果转换为想要的 Java 对象,就要实现 Converter 接口,同时也要实现 RequestConverter 和 ReponseConverter 具体的实现方式可参考源码中 Gson 转换方式。

至此, Retrofit 的源码基本分析完成。
注释的已经上传到 GitHub 上RetrofitAnnotions

个人觉得可以学到的很多知识点:

  1. Retrofit 使用 Build 模式,其实很多开源库都用到了,具体可以看看《Effective Java》 中相关章节,里面有详细的介绍;

  2. 在 Retrofit 构造函数中 使用了 Collection.unmodifiableList(list) 方法,这样返回一个只可遍历的 List, 但不能进行修改的 List;

  3. 使用了动态代理模式;

  4. 检测一个类是否为 Interface , 调用 class.isInterface 即可。
    utils.java 中

 static <T> void validateServiceInterface(Class<T> service) {
    if (!service.isInterface()) {
      throw new IllegalArgumentException("API declarations must be interfaces.");
    }
    // Prevent API interfaces from extending other interfaces. This not only avoids a bug in
    // Android (http://b.android.com/58753) but it forces composition of API declarations which is
    // the recommended pattern.
    if (service.getInterfaces().length > 0) {
      throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
    }
  }

** 参考文章
这些文章都不错,推荐看看。**

  1. 拆轮子系列:拆 Retrofit
  2. Retrofit2 源码解析
发布了58 篇原创文章 · 获赞 20 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/yxhuang2008/article/details/56342639