Retrofit2是怎么实现切换线程的

在上一篇Retrofit是如何支持Kotlin协程的?分析时,并没有发现retrofit使用kotlin协程来切换线程的代码。

那retrofit是在哪里做的线程切换呢?

val testRetrofit: Retrofit = Retrofit.Builder()
    .addConverterFactory(GsonConverterFactory.create())
    .client(okClient)
    .baseUrl("")
    .build()

val testService: TestServiceApi by lazy { testRetrofit.create(TestServiceApi::class.java)}

首先从create方法入手:

public <T> T create(final Class<T> service) {
    validateServiceInterface(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 {
                // If the method is a method from Object then defer to normal invocation.
                if (method.getDeclaringClass() == Object.class) {
                  return method.invoke(this, args);
                }
                args = args != null ? args : emptyArgs;
                return platform.isDefaultMethod(method)
                    ? platform.invokeDefaultMethod(method, service, proxy, args)
                    : loadServiceMethod(method).invoke(args);
              }
            });
  }

1.Proxy.newProxyInstance 是使用的java.lang.reflect提供的代理类。
2.由Platform platform = Platform.get();可知该方法实现和平台相关。

追溯Platform.get(),可以看到:

class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    return "Dalvik".equals(System.getProperty("java.vm.name"))
        ? new Android() //
        : new Platform(true);
  }
  ......
}

再看Android():

 static final class Android extends Platform {
    Android() {
      super(Build.VERSION.SDK_INT >= 24);
    }

    @Override
    public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Nullable
    @Override
    Object invokeDefaultMethod(
        Method method, Class<?> declaringClass, Object object, Object... args) throws Throwable {
      if (Build.VERSION.SDK_INT < 26) {
        throw new UnsupportedOperationException(
            "Calling default methods on API 24 and 25 is not supported");
      }
      return super.invokeDefaultMethod(method, declaringClass, object, args);
    }

    static final class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }

Android类里面的MainThreadExecutor涉及到了线程的切换。好像是找到答案了。
再看它是怎么调用的。追溯defaultCallbackExecutor()方法:

 public Retrofit build() {
      ......
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      ......
      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }

这条线到这里已经到头了。再看create方法里面的loadServiceMethod(method).invoke(args),这里的invoke方法是抽象类ServiceMethod<T>里面的抽象方法invoke。点击他可以找到它的一个唯一实现:

  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    return adapt(call, args);
  }

这里的 adapt(call, args)方法有三个实现。分别是:


adapt方法的三个实现类

都点进去查看,


CallAdapted

SuspendForResponse

对比后发现,他们都调用了

call = callAdapter.adapt(call);

普通的接口方法调用,直接返回了。使用kotlin,suspend修饰的接口方法调用,retrofit增加了网络请求的调用和结果的返回。既是: return KotlinExtensions.awaitResponse(call, continuation);

  //这里是获取接口方法参数列表的最后一个参数,
  //这里已经确认了是suspend修饰的方法,所以该方法的参数中的最后一个参数必定是Continuation类型。
  //这里相当于获取到该方法的回调的对象,协程恢复时就是调用这个回调。
 Continuation<Response<ResponseT>> continuation =
          (Continuation<Response<ResponseT>>) args[args.length - 1];

在SuspendForResponse中,callAdapter是外部传入的。


构造方法赋值
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
      Retrofit retrofit, Method method, RequestFactory requestFactory) {
      ......

    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
      ......
    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 {
      ......
    }
  }

这里的createCallAdapter可以追溯到:

 public CallAdapter<?, ?> nextCallAdapter(
    ......
    int start = callAdapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
      CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }
  ......
  }

这里的callAdapterFactories有点眼熟,原来它在追溯defaultCallbackExecutor()时出现过:

 Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
 List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
断点

总结

refrofit 是通过 在Android平台的线程切换,是通过handler切换到主线程的。

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

推荐阅读更多精彩内容