摘要
通过分析Retrofit源码,了解这款简洁的网络库如何提高我们的工作效率。通过动态代理技术,创建我们接口对象,以提供我们调用接口函数。通过解析接口定义的函数,装配成OkHttp
网络请求所需的数据并发起网络请求。我们可以根据自己的需求,自定义请求适配器和响应转换器。
流程分析
动态代理
我们定义了service
接口,并通过retrofit
对象的create
函数创建了service
类型的对象。通过该对象,我们可以调用在service
接口定义的函数,从而发起定义的网络请求。
1 val service=retrofit.create(service::class.java)
Retrofit
通过动态代理技术生成我们定义service
接口代理对象,因此调用代理对象的函数时都会转发到InvocationHandler
对象的invoke
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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 (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); } }); }
loadServiceMethod
在invoke
函数,我们只关心loadServiceMethod(method).invoke(args)
函数。loadServiceMethod(method)
函数会返回一个ServiceMethod
对象,ServiceMethod
是一个抽象类,唯一直接实现类是HttpServiceMethod
。也就是说这里调用了HttpServiceMethod.invoke(args)
。
1 2 3 4 5 6 7 8 9 10 11 12 13 ServiceMethod<?> loadServiceMethod(Method method) { ServiceMethod<?> result = serviceMethodCache.get(method); if (result != null ) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null ) { result = ServiceMethod.parseAnnotations(this , method); serviceMethodCache.put(method, result); } } return result; }
loadServiceMethod
函数主要先通过缓存serviceMethodCache
获取ServiceMethod
对象,如果缓存中没有获取到ServiceMethod
对象,则通过ServiceMethod.parseAnnotations
解析获取ServiceMethod
对象,并将其放在缓存中。serviceMethodCache
是一个ConcurrentHashMap
,以Method
为Key
,ServiceMethod
为value
。ServiceMethod.parseAnnotations(this, method)
主要是解析Method
对象(我们定义的方法)的注解,参数及注解以及返回类型,然后通过HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)
生成ServerMethod
对象。
ServiceMethod.parseAnnotations
该函数分别调用了RequestFactory
类和HttpServiceMethod
的parseAnnotations
函数。RequestFactory
类主要封装本次网络请求的大多数信息,例如method
,headers
,httpMethod
等等。HttpServiceMethod
是ServerMethod
的子类,主要用来创建请求适配器和数据转换器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 static <T> ServiceMethod<T> parseAnnotations (Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError( method, "Method return type must not include a type variable or wildcard: %s" , returnType); } if (returnType == void .class) { throw methodError(method, "Service methods cannot return void." ); } return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); }
RequestFactory.parseAnnotations
RequestFactory.parseAnnotations(retrofit, method)
通过构建者模式创建RequestFactory
对象。构建的过程主要是解析传递进来的参数method
对象上相关信息,并赋值到RequestFactory
对象相关属性上。Method
对象代表着反射上的一个函数,包含这个该函数的相关信息,例如注解,参数,返回类型等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 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(); } RequestFactory build () { for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } ...... int parameterCount = parameterAnnotationsArray.length; parameterHandlers = new ParameterHandler<?>[parameterCount]; for (int p = 0 , lastParameter = parameterCount - 1 ; p < parameterCount; p++) { parameterHandlers[p] = parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter); } ...... return new RequestFactory(this ); }
build
函数主要解析方法上的注解,参数注解。 parseMethodAnnotation(annotation)
用来解析方法的注解,根据anotation
的类型,例如GET
、POST
等等,然后根据这些方法类型在HTTP报文对应的特性,设置相关属性,例如GET
类型的请求没有请求体hasBody=false
,POST类型的hasBody=true
。
通过parseParameter
解析函数参数注解和获取对应的值。参数注解的解析和函数注解的解析类似,主要检查我们使用方式是否正确和设置相关属性。并且也会判断当前函数是否Kotlin
协程中的挂起函数(后文分析)。
HttpServiceMethod.parseAnnotations
HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory)
又是干了什么呢?将上面解析生成的RequestFactory
,生成请求适配器CallAdapter
和响应转换器Converter
,然后将三者封装到HttpServiceMethod
的子类并返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 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 ]); if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) { responseType = Utils.getParameterUpperBound(0 , (ParameterizedType) responseType); continuationWantsResponse = true ; } else { } adapterType = new Utils.ParameterizedTypeImpl(null , Call.class, responseType); annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); } else { adapterType = method.getGenericReturnType(); } CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); Type responseType = callAdapter.responseType(); ...... Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>( requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); } else { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>( requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, continuationBodyNullable); } }
在创建CallAdatper
和Converter
后,根据是否协程,返回不同的HttpServiceMethod
子类。
createCallAdapter
其中createCallAdapter(retrofit, method, adapterType, annotations);
创建CallAdapted
对象。
1 2 3 4 5 6 7 8 9 private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter ( Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) { try { return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { throw methodError(method, e, "Unable to create call adapter for %s" , returnType); } }
调用retrofit.callAdapter(returnType, annotations)
,根据返回类型retrunType
选择合适的请求适配器。需要注意到的是,这里是从头开始遍历,如果前面适配器符合条件,意味着会被优先选用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null , returnType, annotations); } public CallAdapter<?, ?> nextCallAdapter( @Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { ...... 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; } } ...... }
nextCallAdapter
函数主要通过循环遍历在构建Retrofit
是保存在callAdapterFactories
列表的CallAdapter
,通过其get
函数查看是否匹配。如果Android SDK_INT>=24
返回的是CompletableFutureCallAdapterFactory
,否则返回的是DefaultCallAdapterFactory
。
看看CompletableFutureCallAdapterFactory
对象的get
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != CompletableFuture.class) { return null ; } if (!(returnType instanceof ParameterizedType)) { throw new IllegalStateException( "CompletableFuture return type must be parameterized" + " as CompletableFuture<Foo> or CompletableFuture<? extends Foo>" ); } Type innerType = getParameterUpperBound(0 , (ParameterizedType) returnType); if (getRawType(innerType) != Response.class) { return new BodyCallAdapter<>(innerType); } if (!(innerType instanceof ParameterizedType)) { throw new IllegalStateException( "Response must be parameterized" + " as Response<Foo> or Response<? extends Foo>" ); } Type responseType = getParameterUpperBound(0 , (ParameterizedType) innerType); return new ResponseCallAdapter<>(responseType); }
CompletableFutureCallAdapterFactory
的get
函数根据函数返回类型是否与自己要处理的返回类型一致,不一致则返回null,表示不处理,例如这里是CompletableFuture
。然后进一步检查返回值的合法性,例如是不是泛型对象。最终根据泛型对象最外层类型返回CallAdapter
的子类BodyCallAdapter
或ResponseCallAdapter
。两者的主要区别是其adapt
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 @Override public CompletableFuture<R> adapt (final Call<R> call) { CompletableFuture<R> future = new CallCancelCompletableFuture<>(call); call.enqueue(new BodyCallback(future)); return future; } public CompletableFuture<Response<R>> adapt(final Call<R> call) { CompletableFuture<Response<R>> future = new CallCancelCompletableFuture<>(call); call.enqueue(new ResponseCallback(future)); return future; }
loadServiceMethod(method).invoke(args)
回到loadServiceMethod(method).invoke(args)
,也就是说,这里实际调用了CallAdapter
对象的invoke
函数。
1 2 3 4 5 @Override final @Nullable ReturnT invoke (Object[] args) { Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter); return adapt(call, args); }
invoke
函数主要是构建OkHttpCall
并调用adapt
函数。这里分析ResponseCallAdapter
的adapt
函数。
1 2 3 4 5 6 @Override public CompletableFuture<Response<R>> adapt(final Call<R> call) { CompletableFuture<Response<R>> future = new CallCancelCompletableFuture<>(call); call.enqueue(new ResponseCallback(future)); return future; }
网络请求
adapt
函数调用了OkHttpCall
的enqueue
函数。是不是跟OKHttp
的异步请求很相似。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 @Override public void enqueue (final Callback<T> callback) { Objects.requireNonNull(callback, "callback == null" ); okhttp3.Call call; Throwable failure; synchronized (this ) { if (executed) throw new IllegalStateException("Already executed." ); executed = true ; call = rawCall; failure = creationFailure; if (call == null && failure == null ) { try { call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null ) { callback.onFailure(this , failure); return ; } if (canceled) { call.cancel(); } call.enqueue( new okhttp3.Callback() { @Override public void onResponse (okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { response = parseResponse(rawResponse); } catch (Throwable e) { throwIfFatal(e); callFailure(e); return ; } try { callback.onResponse(OkHttpCall.this , response); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); } } @Override public void onFailure (okhttp3.Call call, IOException e) { callFailure(e); } private void callFailure (Throwable e) { try { callback.onFailure(OkHttpCall.this , e); } catch (Throwable t) { throwIfFatal(t); t.printStackTrace(); } } }); }
通过enqueue
函数的简单分析,就是创建OkHttp
的Call
对象,并调用enqueue
函数。然后发起网络请求,请求成功之后调用parseResponse
解析响应数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Response<T> parseResponse (okhttp3.Response rawResponse) throws IOException { ResponseBody rawBody = rawResponse.body(); rawResponse = rawResponse .newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); int code = rawResponse.code(); if (code < 200 || code >= 300 ) { try { ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } } if (code == 204 || code == 205 ) { rawBody.close(); return Response.success(null , rawResponse); } ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody); try { T body = responseConverter.convert(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { catchingBody.throwIfCaught(); throw e; } }
createResponseConverter
重点地方就是在函数最后的地方调用了T body = responseConverter.convert(catchingBody);
将原始数据转化成我们需要的数据类型。在HttpServiceMethod
的parseAnnotations
函数中createResponseConverter
创建响应数据转换器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter ( Retrofit retrofit, Method method, Type responseType) { Annotation[] annotations = method.getAnnotations(); try { return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { throw methodError(method, e, "Unable to create converter for %s" , responseType); } } public <T> Converter<ResponseBody, T> responseBodyConverter (Type type, Annotation[] annotations) { return nextResponseBodyConverter(null , type, annotations); } public <T> Converter<ResponseBody, T> nextResponseBodyConverter ( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { ...... int start = converterFactories.indexOf(skipPast) + 1 ; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this ); if (converter != null ) { return (Converter<ResponseBody, T>) converter; } } ...... }
响应转换器与请求适配器的创建过程很相似。在创建Retrofit对象时,会将相关转化器保存到converterFactories
列表,通过转化器的responseBodyConverter
函数判断是否处理该响应数据。这里看下OptionalConverterFactory
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 final class OptionalConverterFactory extends Converter .Factory { static final Converter.Factory INSTANCE = new OptionalConverterFactory(); @Override public @Nullable Converter<ResponseBody, ?> responseBodyConverter( Type type, Annotation[] annotations, Retrofit retrofit) { if (getRawType(type) != Optional.class) { return null ; } Type innerType = getParameterUpperBound(0 , (ParameterizedType) type); Converter<ResponseBody, Object> delegate = retrofit.responseBodyConverter(innerType, annotations); return new OptionalConverter<>(delegate); } @IgnoreJRERequirement static final class OptionalConverter <T > implements Converter <ResponseBody , Optional <T >> { final Converter<ResponseBody, T> delegate; OptionalConverter(Converter<ResponseBody, T> delegate) { this .delegate = delegate; } @Override public Optional<T> convert (ResponseBody value) throws IOException { return Optional.ofNullable(delegate.convert(value)); } } }
responseBodyConverter
逻辑很简单,判断放回类型Type
是不是Optional.class
,然后返回OptionalConverter
。那么网络成功返回数据就会调用convert
函数,而这个直接委托给下一个转化器。
而在构建converterFactories
列表的时候,会优先添加BuiltInConverters
,然后是我们自定义的转换器,最后如果Android SDK>=24,才添加OptionalConverterFactory
。也就是说从这里可以看到优先权。
而构建callAdapterFactories
列表,则是先我们自定义的,再是平台默认的适配器。
通常情况下,我们都会添加GsonConverterFactory
适配器,将gson
转化成对象类型。
1 2 3 4 5 6 @Override public Converter<ResponseBody, ?> responseBodyConverter( Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonResponseBodyConverter<>(gson, adapter); }
GsonResponseBodyConverter
的convert
函数。
1 2 3 4 5 6 7 8 9 10 11 12 public T convert (ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { T result = adapter.read(jsonReader); if (jsonReader.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed." ); } return result; } finally { value.close(); } }
到这里,Retrofit整个源码流程就分析完了。所以也应该学会了如何自定适配器和转换器了。
协程
Retrofit在目前版本2.6.0开始就已经支持协程,即允许在接口中定义挂起函数。那Retrofit如何确定接口定义的函数是挂起函数呢?
在上一节分析RequestFactory.parseAnotations
中分析函数注解,说到parseParameter
解析函数参数注解,有提到判断函数是否挂起函数。来看是如何判断的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private @Nullable ParameterHandler<?> parseParameter( int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) { ······ if (result == null ) { if (allowContinuation) { try { if (Utils.getRawType(parameterType) == Continuation.class) { isKotlinSuspendFunction = true ; return null ; } } catch (NoClassDefFoundError ignored) { } } throw parameterError(method, p, "No Retrofit annotation found." ); } return result; }
判断是否协程函数有三个条件:
函数参数没有注解
该参数是在函数中的最后一个位置
该参数的类型是Continuation.class
但这跟我们理解中协程的挂起函数区别有点大啊。因为这是我们理解中的Kotlin
挂起函数,当它编译后成Java字节码后,会自动在函数最后一个参数增加Continuation
类型的参数。
Kotlin
函数
Java
函数
1 void getData(Continuation c)
通过解析接口中函数的最后一个参数没有注解,而且类型为Continuation
时,就确定为了一个Kotlin协程挂起函数,并将ReqeustFactory
的isKotlinSuspendFunction
设置为true
。
在HttpServiceMethod.parseAnnotations
解析时根据isKotlinSuspendFunction
来走不同的分支,例如isKotlinSuspendFunction=true
情况下,返回的是SuspendForResponse
,=false
情况下,返回的是CallAdapter
。看看具体处理了哪些工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 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 ]); if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) { responseType = Utils.getParameterUpperBound(0 , (ParameterizedType) responseType); continuationWantsResponse = true ; } else { } adapterType = new Utils.ParameterizedTypeImpl(null , Call.class, responseType); annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); } else { adapterType = method.getGenericReturnType(); } CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); Type responseType = callAdapter.responseType(); ...... Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType); okhttp3.Call.Factory callFactory = retrofit.callFactory; if (!isKotlinSuspendFunction) { return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter); } else if (continuationWantsResponse) { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>( requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter); } else { return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>( requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, continuationBodyNullable); } }
在这里根据接口的函数返回类型的不同,返回SuspendForResponse
或者SuspendForBody
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 static final class SuspendForResponse <ResponseT > extends HttpServiceMethod <ResponseT , Object > { private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter; SuspendForResponse( RequestFactory requestFactory, okhttp3.Call.Factory callFactory, Converter<ResponseBody, ResponseT> responseConverter, CallAdapter<ResponseT, Call<ResponseT>> callAdapter) { super (requestFactory, callFactory, responseConverter); this .callAdapter = callAdapter; } @Override protected Object adapt (Call<ResponseT> call, Object[] args) { call = callAdapter.adapt(call); Continuation<Response<ResponseT>> continuation = (Continuation<Response<ResponseT>>) args[args.length - 1 ]; try { return KotlinExtensions.awaitResponse(call, continuation); } catch (Exception e) { return KotlinExtensions.suspendAndThrow(e, continuation); } } }
通过调用OkHttp
的Call
扩展函数来实现网络请求。我们知道非协程下是通过创建OkHttpCall来实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 suspend fun <T : Any> Call<T>.await(): T { return suspendCancellableCoroutine { continuation -> continuation.invokeOnCancellation { cancel() } enqueue(object : Callback<T> { 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) } }) } }
也就是说,非协程与协程下的Retrofit的工作流程差不多。协程情况下,在RequestFactory
解析,确定是协程,在HttpserviceMethod
解析走不同的路径,通过Call
扩展函数实现网络请求。
动态代理
说到动态代理,总是离不开静态代理和代理模式。静态代理总是要写接口,然后代理类和被代理类实现该接口,客户端通过代理类使用接口提供的功能,而代理类把功能实际的工作转到被代理类。问题在哪里,每次我们都懂得去实现代理类和代理类,如果很多个接口,这样会很累的,毕竟程序员都是懒的。再说如果这样,用Retrofit这种第三方库,怎么知道用户创建什么样的接口,怎么去实现他们功能?那就是利用Java的动态代理技术了。动态代理在使用上也可以理解是一套模板。
首先,定义接口,以及实现类,也就是我们对外提供的功能。
1 2 3 4 5 6 7 8 9 10 11 public interface Service { void coding(); } public class CoderService implements Service { @Override public void coding() { System.out.println("提供编程服务"); } }
第二,实现InvocationHandler
的子类。核心点在于实现invoke
函数,调用接口的函数都会转到这里来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Handler implements InvocationHandler { private Object service; public Handler (Object service) { this .service = service; } @Override public Object invoke (Object o, Method method, Object[] objects) throws Throwable { System.out.println("开发了" ); method.invoke(service,objects); System.out.println("结束了" ); return null ; } }
最后,创建Proxy.newProxyInstance
接口对象。在Java中,接口和抽象类是不能被直接实例化的。
1 2 3 4 5 6 7 8 public class Main { public static void main (String[] args) { Service service = new CoderService(); InvocationHandler handler = new Handler(service); Service se = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(), new Class[]{Service.class}, handler); se.coding(); } }
这样就可以通过实例化的接口对象,使用相关功能。
Retrofit
通过在InvocationHandler
的invoke
解析Method
来获得网络请求所需要的的数据。
总结
Retrofit通过Java动态代理技术生成我们请求接口的对象,而我们调用对象的任何函数时,其实都转到InvocationHandler
对象的invoke
函数。而invoke
函数的主要工作就是解析我们在接口中定义函数,包括解析注解,参数注解及值,以及返回类型,然后封装到RequestFactory
,然后通过HttpServiceMethod.parseAnnotations
函数,查找合适的请求适配器和响应转换器,最后将RequestFactory
和适配器、转换器封装成HttpServiceMethod
的子类,并调用其invoke
函数,通过OkHttp
发起网络请求。
通过源码分析,我们知道,一个优秀的的框架都会使用缓存,例如这里方法的解析,OkHttp
请求的缓存。同时也知道Retrofit目前已经支持协程,即挂起函数。