在上一篇Retrofit是如何支持Kotlin協(xié)程的?分析時踢械,并沒有發(fā)現(xiàn)retrofit使用kotlin協(xié)程來切換線程的代碼瞎颗。
那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();可知該方法實現(xiàn)和平臺相關(guān)漠嵌。
追溯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涉及到了線程的切換。好像是找到答案了儒鹿。
再看它是怎么調(diào)用的化撕。追溯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);
}
這條線到這里已經(jīng)到頭了。再看create方法里面的loadServiceMethod(method).invoke(args)约炎,這里的invoke方法是抽象類ServiceMethod<T>里面的抽象方法invoke植阴。點擊他可以找到它的一個唯一實現(xiàn):
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
這里的 adapt(call, args)方法有三個實現(xiàn)。分別是:
都點進去查看圾浅,
對比后發(fā)現(xiàn)掠手,他們都調(diào)用了
call = callAdapter.adapt(call);
普通的接口方法調(diào)用,直接返回了狸捕。使用kotlin喷鸽,suspend修飾的接口方法調(diào)用,retrofit增加了網(wǎng)絡(luò)請求的調(diào)用和結(jié)果的返回灸拍。既是: return KotlinExtensions.awaitResponse(call, continuation);
//這里是獲取接口方法參數(shù)列表的最后一個參數(shù)做祝,
//這里已經(jīng)確認了是suspend修飾的方法,所以該方法的參數(shù)中的最后一個參數(shù)必定是Continuation類型鸡岗。
//這里相當于獲取到該方法的回調(diào)的對象剖淀,協(xié)程恢復時就是調(diào)用這個回調(diào)。
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()時出現(xiàn)過:
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
總結(jié)
refrofit 是通過 在Android平臺的線程切換,是通過handler切換到主線程的捌刮。