Retrofit2.6.1源码分析
1. Retrofit是怎么将回调函数放到主线程的?
看new Retrofit.Builder()的Builder方法
当返回对象为Call,就会使用默认的DefaultCallAdapterFactory
static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); //也就是在这里执行网络请求后,线程转换了 delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { // 这里的callbackExecutor就是上图中的mainThreadExecutor callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation. callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled")); } else { callback.onResponse(ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); }
2 retrofit的初始化
2.1 .build()方法干了写什么?
//new Retrofit.Builde().build()方法 public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } // 配置回调方法执行器(callbackExecutor)- Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } //配置网络请求适配器工厂(CallAdapterFactory) // Make a defensive copy of the adapters and add the default Call adapter. List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); //CompletableFutureCallAdapterFactory中包含BodyCallAdapter与ResponseCallAdapter(后面会讲到) callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));//注意Android extends Platform //配置数据转换器工厂:converterFactory // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>( 1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize()); // Add the built-in converter factory first. This prevents overriding its behavior but also // ensures correct behavior when using converters that consume all types. converterFactories.add(new BuiltInConverters()); converterFactories.addAll(this.converterFactories); converterFactories.addAll(platform.defaultConverterFactories()); //也就是将开始将的handler、defaultCallAdapterFactories与自己添加的CallAdapterFactories、默认的converterFactorie与添加的converterFactories存起来了 return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); } }
获取合适的网络请求适配器和数据转换器都是从adapterFactories和converterFactories集合的首位-末位开始遍历,因此集合中的工厂位置越靠前就拥有越高的使用权限
callAdapterFactories里面的callAdapter中包含了执行网络请求的call对象,那么用哪个call去执行网络请求呢?匹配规则
RxJava2CallAdapterFactory:对应返回值Observable CompletableFutureCallAdapterFactory:如果返回值是Response -> BodyCallAdapter 否则 ResponseCallAdapter DefaultCallAdapterFactory: 对应返回值为Call,也就是纯retrofit的时候就是它了 BuiltInConverters: 返回类型为ResponseBody、Void、Unit OptionalConverterFactory: Java8的新特性,Optional.ofNullable(delegate.convert(value)) 避免空指针的
2.2 .create()方法中的loadServiceMethod(method).invoke()方法
public <T> T create(final Class<T> service) { Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(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); } if (platform.isDefaultMethod(method)) { //java8 后接口可以写默认方法 return platform.invokeDefaultMethod(method, service, proxy, args); } //关键是看这两个方法 return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
先看loadServiceMethod()方法:
ServiceMethod.parseAnnotations(this, method); static RequestFactory parseAnnotations(Retrofit retrofit, Method method) { return new Builder(retrofit, method).build(); } Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); } //比如这样的一个接口 @POST fun getLiveRoomUserSig(@Url url: String, @Body body: HashMap<String, String>): Observable<HttpResponse<JBLiveRoomUserSigModel>> methodAnnotations:POST 也就是方法上的注解 parameterTypes: String 与 HashMap 也就是方法参数类型 parameterAnnotationsArray:URL 与 Body 也就是方法的参数注解
这里我们需要关注下对parameterAnnotationsArray的处理,也就是将我们的参数(比如map)转换成发起网络请求的数据
RequestFactory build() { for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); //请求方式 POST Get等 的处理 } ...省略部分代码 //方法上的参数注解处理,比如常用的:@FieldMap @Body int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0, lastParameter = parameterCount - 1; p < parameterCount; p++) { //需要注意 这里 方法参数注解 与 方法参数类型 是 一一匹配的 不同的是parameterAnnotationsArray是个二维数组,因为一个参数可能有多个注解 parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); } private @Nullable ParameterHandler<?> parseParameter( int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) { ParameterHandler<?> result = null; if (annotations != null) { for (Annotation annotation : annotations) { ParameterHandler<?> annotationAction = parseParameterAnnotation(p, parameterType, annotations, annotation); if (annotationAction == null) { continue; } //annotations就是上面说的多个注解,这里遍历如果一个参数找到多个Retrofit批注 就抛异常了 if (result != null) { throw parameterError(method, p, "Multiple Retrofit annotations found, only one allowed."); } result = annotationAction; } } //紧接着 parseParameterAnnotation 跟进来 这里我们看下常用的 if (annotation instanceof Body) { Converter<?, RequestBody> converter; try { converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw parameterError(method, e, p, "Unable to create @Body converter for %s", type); } gotBody = true; return new ParameterHandler.Body<>(method, p, converter); }else if (annotation instanceof FieldMap) { //比如 @FormUrlEncoded 的时候 用的这个, if (!isFormEncoded) { //可见如果用FieldMap 而不是isFormEncoded的请求方式,就抛异常了 throw parameterError(method, p,"@FieldMap parameters can only be used with form encoding."); } Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations); //默认得到的是 BuiltInConverters.ToStringConverter.INSTANCE return new ParameterHandler.FieldMap<>(method, p, valueConverter, ((FieldMap) annotation).encoded()); }
解析完后将每个参数对应的ParameterHandler 都保存到了 parameterHandlers数组中, 再创建RequestFactory对象
也就是说:上面拿到了对请求体的解析,对网络请求前做处理这里需要注意一个方法:RequestFactory类中有个create()方法,如下图,返回了一个okhttp3.Request对象
在哪里调用?
继续看这个方法在哪些地方调用了:
看方法名,很明显这都是在执行网络请求的时候调用的,也是真正执行网络请求的地方。
图中createRawCall()方法三个调用的地方稍后再做具体分析,先看下requestFactory.create()方法干了些啥
okhttp3.Request create(Object[] args) throws IOException { @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types. ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers; int argumentCount = args.length;//args 就是参数的个数,retrofit代理那块传过来的 RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart); if (isKotlinSuspendFunction) { // The Continuation is the last parameter and the handlers array contains null at that index. argumentCount--; } List<Object> argumentList = new ArrayList<>(argumentCount); for (int p = 0; p < argumentCount; p++) { argumentList.add(args[p]); handlers[p].apply(requestBuilder, args[p]);//遍历parameterHandlers 执行apply方法,为requestBuilder设置请求体 } //再使用requestBuilder构建网络请求的Request对象 return requestBuilder.get() .tag(Invocation.class, new Invocation(method, argumentList)) .build(); }
继续上面代码的执行流程,就到了下面这个方法,这里就对应了响应数据与网络请求相关的处理:
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) { boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction; boolean continuationWantsResponse = false; boolean continuationBodyNullable = false; Annotation[] annotations = method.getAnnotations(); Type adapterType; if (isKotlinSuspendFunction) { Type[] parameterTypes = method.getGenericParameterTypes(); Type responseType = Utils.getParameterLowerBound(0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]); //ParameterizedType 代表是 参数化类型,简单点说 就是responseType是一个带泛形的类 if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) { // Unwrap the actual body type from Response<T>. responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType); continuationWantsResponse = true; } else { // TODO figure out if type is nullable or not // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class) // Find the entry for method // Determine if return type is nullable or not } adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType); annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); } else { adapterType = method.getGenericReturnType(); } //获取相匹配的callAdapter 该callAdapter做了啥? 看下图 CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); // 拿到的responseType是啥? 看下图 当配合RxJava2CallAdapterFactory时, // adapterType = Observable<T> responseType就是我们Observable<T> 的T的类型 Type responseType = callAdapter.responseType(); if (responseType == okhttp3.Response.class) { throw methodError(method, "'" + getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } if (responseType == Response.class) { throw methodError(method, "Response must include generic type (e.g., Response<String>)"); } // TODO support Unit for Kotlin? if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) { throw methodError(method, "HEAD method must use Void as response type."); } //根据需要的返回类型,来匹配对网络请求成功的json数据的解析类 具体看下图, 最后返回了GsonResponseBodyConverter Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; //如果返回的类型不是 Suspend 函数 就会返回CallAdapter, 比如当我们使用Rxjava2Adapter时,定义的接口返回的Observable if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. //如果是 Suspend 函数, 判断方法返回值是不是Response return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); } else { //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object. //如果是直接返回实体类的,那么就走到这里来了,注意下面会再次提到这 return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, continuationBodyNullable); } }
上面调用createCallAdapter 打了个断点,可看到createCallAdapter方法里的参数信息如下
再跟下去,
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; //如果我们使用的Rxjava+Retrofit的模式,那么根据上面中的参数,匹配上的CallAdapter就是RxJava2CallAdapter了 } }
上面返回adapter后,紧接着获取接口请求后的返回类型callAdapter.responseType();
response转换器的创建过程
也就是说loadServiceMethod(method)该方法主要是创建并加载ServiceMehod,用于解析网络请求接口参数、网络请求适配器、response数据解析器的工作。
2.3. 返回HttpServiceMethod后就调用.invoke()方法,返回OkhttpCall对象
requestFactory 里面包含请求方式、请求Url、请求体
callFactory 为OkhttpClient对象
responseConverter 为我们的json转换,比如GsonConverterFactory
然后将这些数据都放到OkHttpCall中(OkHttpCall<T> implements Call),这里面有两个方法,用来执行网络请求:同步请求execute() 与异步请求 enqueue()
这两个方法在哪里开始执行的呢?以RxJava2CallAdapter为例,所以上图中adapter对应的来到
点击去就可以看到在subscribeActual()方法中执行了对应的请求,
点击call.execute(),就来到了OkHttpCall的execute()
public Response<T> execute() throws IOException { okhttp3.Call call; synchronized (this) { if (call == null) { try { call = rawCall = createRawCall(); //这里也就是上文所指的稍后分析的问题了 } catch (IOException | RuntimeException | Error e) { } } } return parseResponse(call.execute()); //解析请求成功后的数据
请求成功后,调用GsonResponseBodyConverter的convert()方法,返回我们需要的实体类,
OkHttpCall - > parseResponse
并且还可以发现取消网络请求的操作也在CallExecuteObservable里面。
那么如果是用协程配合retrofit,网络请求又是怎么取消的呢?
//当只使用Retrofit的时候,接口是这样定义的 返回Call @GET("article/list/1/json") fun getHomeList() : Call<BaseResponse<Data>> //当使用协程与Retrofit配合使用的时候,方法上加了个suspend @GET("article/list/1/json") suspend fun getHomeList() : BaseResponse<Data> //发起网络请求 viewModelScope.launch { withContext(Dispatchers.IO) { getHomeList() } }
3. 为啥使用viewModelScope,能自动取消网络请求呢?
当使用这种模式的时候,网络请求发起的包装类为:SuspendForBody (上面有提到哟)
static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> { private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter; private final boolean isNullable; SuspendForBody(RequestFactory requestFactory, okhttp3.Call.Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter, CallAdapter<ResponseT, Call<ResponseT>> callAdapter, boolean isNullable) { super(requestFactory, callFactory, responseConverter); this.callAdapter = callAdapter; this.isNullable = isNullable; } @Override protected Object adapt(Call<ResponseT> call, Object[] args) { call = callAdapter.adapt(call); //noinspection unchecked Checked by reflection inside RequestFactory. Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1]; //OkHttp Call.enqueue()带有异常,协程将拦截Continuation的后续调用 try { return isNullable //为false ? KotlinExtensions.awaitNullable(call, continuation) : KotlinExtensions.await(call, continuation); } catch (Exception e) { return KotlinExtensions.yieldAndThrow(e, continuation); } } }
再往下走
suspend fun <T : Any> Call<T>.await(): T { return suspendCancellableCoroutine { continuation -> continuation.invokeOnCancellation { cancel() //取消网络请求 } enqueue(object : Callback<T> { //发起网络请求 这里是OkHttpCall的enqueue方法 override fun onResponse(call: Call<T>, response: Response<T>) { if (response.isSuccessful) { val body = response.body() if (body == null) { val invocation = call.request().tag(Invocation::class.java)!! val method = invocation.method() val e = KotlinNullPointerException("Response from " + method.declaringClass.name + '.' + method.name + " was null but response body type was declared as non-null") continuation.resumeWithException(e) } else { continuation.resume(body) } } else { continuation.resumeWithException(HttpException(response)) } } override fun onFailure(call: Call<T>, t: Throwable) { continuation.resumeWithException(t) } }) } }
这里就可以看到看到了enqueue的执行,这里执行了Call类中的enqueue方法,并拿到返回值,通过continuation把结果和异常统统返回给协程的调用者。
continuation:顾名思义,继续、持续的意思,协程中的类,表示一个协程的延续,协程执行的时候会挂起,这个类就用于挂起完成之后的后续工作,看起来相当于一个回调。
继续跟进查看OkHttpCall的enqueue方法
call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { response = parseResponse(rawResponse);//将网络请求成功后的Response转换成我们的实体类 } catch (Throwable e) { throwIfFatal(e); callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response);//再回掉出去 } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); // TODO this is not great } }
流程图: