在上一篇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)方法有三个实现。分别是:
都点进去查看,
对比后发现,他们都调用了
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切换到主线程的。