Retrofit 2.6.0 之后支持接口suspend函数配合协程使用,举个例子:
ApiService
1interface LoginApiService : BaseService { 2 @GET("/wxarticle/chapters/json") 3 suspend fun getChapters(): BaseResponse<List<Chapters>> 4}
Repository
1class LoginRepository : BaseRepository() { 2 suspend fun getChapters(): BaseResponse<List<Chapters>> { 3 val service = retrofit.create(LoginApiService::class.java) 4 return withContext(Dispatchers.IO) { 5 service.getChapters() 6 } 7 } 8} 9
从API调用入手Retrofit.create()
1 2 public <T> T create(final Class<T> service) { 3 validateServiceInterface(service); 4 return (T) 5 Proxy.newProxyInstance( 6 service.getClassLoader(), 7 new Class<?>[] {service}, 8 new InvocationHandler() { 9 private final Platform platform = Platform.get(); 10 private final Object[] emptyArgs = new Object[0]; 11 12 @Override 13 public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) 14 throws Throwable { 15 // If the method is a method from Object then defer to normal invocation. 16 if (method.getDeclaringClass() == Object.class) { 17 return method.invoke(this, args); 18 } 19 args = args != null ? args : emptyArgs; 20 return platform.isDefaultMethod(method) 21 ? platform.invokeDefaultMethod(method, service, proxy, args) 22 : loadServiceMethod(method).invoke(args); 23 } 24 }); 25 } 26
动态代理,拦截接口方法,实际调用Retrofit.loadServiceMethod()
1 2 ServiceMethod<?> loadServiceMethod(Method method) { 3 ServiceMethod<?> result = serviceMethodCache.get(method); 4 if (result != null) return result; 5 6 synchronized (serviceMethodCache) { 7 result = serviceMethodCache.get(method); 8 if (result == null) { 9 result = ServiceMethod.parseAnnotations(this, method); 10 serviceMethodCache.put(method, result); 11 } 12 } 13 return result; 14 }
ServiceMethod.parseAnnotations()
1static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) { 2 RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); 3 4 Type returnType = method.getGenericReturnType(); 5 if (Utils.hasUnresolvableType(returnType)) { 6 throw methodError( 7 method, 8 "Method return type must not include a type variable or wildcard: %s", 9 returnType); 10 } 11 if (returnType == void.class) { 12 throw methodError(method, "Service methods cannot return void."); 13 } 14 15 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); 16 }
RequestFactory.parseAnnotations()
1 static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { 2 return new Builder(retrofit, method).build(); 3 } 4new Builder(retrofit, method).build() 5 6RequestFactory build() { 7 for (Annotation annotation : methodAnnotations) { 8 parseMethodAnnotation(annotation); 9 } 10 ...... 11 int parameterCount = parameterAnnotationsArray.length; 12 parameterHandlers = new ParameterHandler<?>[parameterCount]; 13 for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) { 14 parameterHandlers[p] = 15 parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); 16 } 17 ...... 18 return new RequestFactory(this); 19 }
build()中遍历解析注解,parseParameter()中判断是否为挂起函数。
RequestFactory.parseParameter()
1 ...... 2if (Utils.getRawType(parameterType) == Continuation.class) { 3 isKotlinSuspendFunction = true; 4 return null; 5 } 6 ......
回看ServiceMethod.parseAnnotations()返回值HttpServiceMethod.parseAnnotations()
1 boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; 2 boolean continuationWantsResponse = false; 3 4 if (isKotlinSuspendFunction) { 5 if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) { 6 responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType); 7 continuationWantsResponse = true; 8 } 9 } 10 11 if (!isKotlinSuspendFunction) { 12 return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); 13 } else if (continuationWantsResponse) { 14 //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. 15 return (HttpServiceMethod<ResponseT, ReturnT>) 16 new SuspendForResponse<>( 17 requestFactory, 18 callFactory, 19 responseConverter, 20 (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); 21 } else { 22 //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. 23 return (HttpServiceMethod<ResponseT, ReturnT>) 24 new SuspendForBody<>( 25 requestFactory, 26 callFactory, 27 responseConverter, 28 (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, 29 continuationBodyNullable); 30 }
这里走else if
1return (HttpServiceMethod<ResponseT, ReturnT>) 2 new SuspendForResponse<>( 3 requestFactory, 4 callFactory, 5 responseConverter, 6 (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter)
retrofit.loadServiceMethod()最终返回SuspendForResponse
1 static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> { 2 private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter; 3 private final boolean isNullable; 4 5 SuspendForBody( 6 RequestFactory requestFactory, 7 okhttp3.Call.Factory callFactory, 8 Converter<ResponseBody, ResponseT> responseConverter, 9 CallAdapter<ResponseT, Call<ResponseT>> callAdapter, 10 boolean isNullable) { 11 super(requestFactory, callFactory, responseConverter); 12 this.callAdapter = callAdapter; 13 this.isNullable = isNullable; 14 } 15 16 @Override 17 protected Object adapt(Call<ResponseT> call, Object[] args) { 18 call = callAdapter.adapt(call); 19 Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1]; 20 try { 21 return isNullable 22 ? KotlinExtensions.awaitNullable(call, continuation) 23 : KotlinExtensions.await(call, continuation); 24 } catch (Exception e) { 25 return KotlinExtensions.suspendAndThrow(e, continuation); 26 } 27 } 28 }
回看loadServiceMethod().invoke()->ServiceMethod抽象方法
1abstract @Nullable T invoke(Object[] args)
子类HttpServiceMethod.invoke()
1 @Override 2 final @Nullable ReturnT invoke(Object[] args) { 3 Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); 4 return adapt(call, args); 5 } 6 7 protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
调用到抽象方法adapt(),loadServiceMethod()方法返回值SuspendForResponse继承HttpServiceMethod重写了该方法
1 @Override 2 protected Object adapt(Call<ResponseT> call, Object[] args) { 3 call = callAdapter.adapt(call); 4 5 //noinspection unchecked Checked by reflection inside RequestFactory. 6 Continuation<Response<ResponseT>> continuation = 7 (Continuation<Response<ResponseT>>) args[args.length - 1]; 8 9 // See SuspendForBody for explanation about this try/catch. 10 try { 11 return KotlinExtensions.awaitResponse(call, continuation); 12 } catch (Exception e) { 13 return KotlinExtensions.suspendAndThrow(e, continuation); 14 } 15 }
KotlinExtensions.awaitResponse()
1suspend fun <T> Call<T>.awaitResponse(): Response<T> { 2 return suspendCancellableCoroutine { continuation -> 3 continuation.invokeOnCancellation { 4 cancel() 5 } 6 enqueue(object : Callback<T> { 7 override fun onResponse(call: Call<T>, response: Response<T>) { 8 continuation.resume(response) 9 } 10 11 override fun onFailure(call: Call<T>, t: Throwable) { 12 continuation.resumeWithException(t) 13 } 14 }) 15 } 16}
call.enqueue()内部调用continuation.resume(response)将返回值传给挂起函数,流程结束。
