Retrofit 枯燥无趣的源码分析
↓推荐关注↓
摘要
通过分析Retrofit源码,了解这款简洁的网络库如何提高我们的工作效率。通过动态代理技术,创建我们接口对象,以提供我们调用接口函数。通过解析接口定义的函数,装配成OkHttp
网络请求所需的数据并发起网络请求。我们可以根据自己的需求,自定义请求适配器和响应转换器。
流程分析
动态代理
我们定义了service
接口,并通过retrofit
对象的create
函数创建了service
类型的对象。通过该对象,我们可以调用在service
接口定义的函数,从而发起定义的网络请求。
val service=retrofit.create(service::class.java)
Retrofit
通过动态代理技术生成我们定义service
接口代理对象,因此调用代理对象的函数时都会转发到InvocationHandler
对象的invoke
函数。
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 {
//判断是否Obect的默认方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
args = args != null ? args : emptyArgs;
//判断是否特定平台的方法,例如Android
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)
。
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
的子类,主要用来创建请求适配器和数据转换器。
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
对象代表着反射上的一个函数,包含这个该函数的相关信息,例如注解,参数,返回类型等。
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() {
//1、解析方法上注解
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
的子类并返回。
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) {
// 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(); //获取方法的返回类型
}
//遍历Retrofit的CallAdapter列表,寻找是否有符合处理该adapterType的CallAdapter
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
......
//遍历Retrofit的转换器列表,寻找合适的转换器
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);//非协程情况下,HtttpServerMethod的子类
} else if (continuationWantsResponse) {
//使用了协程,且返回类型Response
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//使用了协程,且返回类型ResponseBody
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
对象。
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
调用retrofit.callAdapter(returnType, annotations)
,根据返回类型retrunType
选择合适的请求适配器。需要注意到的是,这里是从头开始遍历,如果前面适配器符合条件,意味着会被优先选用。
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
函数。
@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) {
// Generic type is not Response<T>. Use it for body-only adapter.
return new BodyCallAdapter<>(innerType);
}
// Generic type is Response<T>. Extract T and create the Response version of the adapter.
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
函数。
//BodyCallAdapter
@Override
public CompletableFuture<R> adapt(final Call<R> call) {
CompletableFuture<R> future = new CallCancelCompletableFuture<>(call);
call.enqueue(new BodyCallback(future));
return future;
}
//ResponseCallAdapter
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
函数。
@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
函数。
@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
的异步请求很相似。
@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(); // TODO this is not great
}
}
@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(); // TODO this is not great
}
}
});
}
通过enqueue
函数的简单分析,就是创建OkHttp
的Call
对象,并调用enqueue
函数。然后发起网络请求,请求成功之后调用parseResponse
解析响应数据。
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse =
rawResponse
.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
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) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
createResponseConverter
重点地方就是在函数最后的地方调用了T body = responseConverter.convert(catchingBody);
将原始数据转化成我们需要的数据类型。在HttpServiceMethod
的parseAnnotations
函数中createResponseConverter
创建响应数据转换器。
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) { // Wide exception range because factories are user code.
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) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
......
}
响应转换器与请求适配器的创建过程很相似。在创建Retrofit对象时,会将相关转化器保存到converterFactories
列表,通过转化器的responseBodyConverter
函数判断是否处理该响应数据。这里看下OptionalConverterFactory
。
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
转化成对象类型。
@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
函数。
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
解析函数参数注解,有提到判断函数是否挂起函数。来看是如何判断的。
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) {//参数类型为Continuation
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
判断是否协程函数有三个条件:
函数参数没有注解 该参数是在函数中的最后一个位置 该参数的类型是 Continuation.class
但这跟我们理解中协程的挂起函数区别有点大啊。因为这是我们理解中的Kotlin
挂起函数,当它编译后成Java字节码后,会自动在函数最后一个参数增加Continuation
类型的参数。
Kotlin
函数
suspend fun getData()
Java
函数
void getData(Continuation c)
通过解析接口中函数的最后一个参数没有注解,而且类型为Continuation
时,就确定为了一个Kotlin协程挂起函数,并将ReqeustFactory
的isKotlinSuspendFunction
设置为true
。
在HttpServiceMethod.parseAnnotations
解析时根据isKotlinSuspendFunction
来走不同的分支,例如isKotlinSuspendFunction=true
情况下,返回的是SuspendForResponse
,=false
情况下,返回的是CallAdapter
。看看具体处理了哪些工作。
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;
//协程情况下,与非协程情况下类似,获取返回类型adapterType,用于创建CallAdapter
if (isKotlinSuspendFunction) {
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType =
Utils.getParameterLowerBound(
0, (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
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<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) {
////使用了协程,且返回类型Response
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
////使用了协程,且返回类型ResponseBody
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
在这里根据接口的函数返回类型的不同,返回SuspendForResponse
或者SuspendForBody
。
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);
//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation<Response<ResponseT>> continuation =
(Continuation<Response<ResponseT>>) args[args.length - 1];
// See SuspendForBody for explanation about this try/catch.
try {
return KotlinExtensions.awaitResponse(call, continuation);
} catch (Exception e) {
return KotlinExtensions.suspendAndThrow(e, continuation);
}
}
}
通过调用OkHttp
的Call
扩展函数来实现网络请求。我们知道非协程下是通过创建OkHttpCall来实现的。
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的动态代理技术了。动态代理在使用上也可以理解是一套模板。
首先,定义接口,以及实现类,也就是我们对外提供的功能。
public interface Service {
void coding();
}
public class CoderService implements Service {
@Override
public void coding() {
System.out.println("提供编程服务");
}
}
第二,实现InvocationHandler
的子类。核心点在于实现invoke
函数,调用接口的函数都会转到这里来。
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中,接口和抽象类是不能被直接实例化的。
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目前已经支持协程,即挂起函数。
转自:掘金 新小梦
https://juejin.cn/post/6941585326675034143
- EOF -
看完本文有收获?请分享给更多人
推荐关注「安卓开发精选」,提升安卓开发技术
点赞和在看就是最大的支持❤️