在阅读源码的时候,里面大量使用到了Type这类。那这个类是干嘛的呢?
java泛型在运行时会被擦除,我们就无法得到在编译时期的泛型信息。因此java提供了
Type,它可以让我们在运行的时候也能得到这些信息。
类型擦除是指泛型在运行的时候会去擦除泛型的类信息
接口解析过程:
1 2 3 4 5 6 interface ApiInterFace { @Streaming @GET suspend fun downloadFile (@Url fileUrl: String ?) : Response<ResponseBody> }
使用Retrofit调用create(Class service)得时候,会去解析我们的service方法,service也就是上面我演示的ApiInterface方法。他会去解析这个接口的downloadFile方法的注解,泛型参数信息,和所有参数上面的注解信息。因为现在引入了Kotlin的协程,所以在解析方法的注解的时候,会判断最后一个注解是不是协程,如果是的话会给参数isKotlinSuspendFunction 标记为true。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 final class RequestFactory { static final class Builder { Builder(Retrofit retrofit, Method method) { this .retrofit = retrofit; this .method = method; this .methodAnnotations = method.getAnnotations(); this .parameterTypes = method.getGenericParameterTypes(); this .parameterAnnotationsArray = method.getParameterAnnotations(); } } }
关于方法的注解解析都在RequestFactory.java 类完成。
Retrofit为啥要使用动态代理?
在Retrofit使用动态代理可以适配新出现的技术,比如以前使用Okhttp的时候,我们都是要创建一个Call对象,然后通过这个call对象去进行网络请求。然后现在出现了kotlin的协程,kotlin由于使用了动态代理,我们可以去通过代理创建可以搭配kolin的协程进行的网络请求。
在Retrofit的代理实现的类是继承自ServiceMethod抽象类。目前Retrofit已知的有:
classDiagram
HttpServiceMethod--|>ServiceMethod
SuspendForBody--|>HttpServiceMethod
SuspendForResponse--|>HttpServiceMethod
CallAdapted--|> HttpServiceMethod
ServiceMethod : +ServiceMethod parseAnnotations()
ServiceMethod : +T invoke()
class HttpServiceMethod{
+HttpServiceMethod parseAnnotations()
-CallAdapter createCallAdapter()
-Converter createREsponseConverter()
+ReturnT invoke()
+ReturnT adapter()
-RequestFactory requestFory
-okhttp3.Call.Factory callFactory
-Converter responseConverter
}
class CallAdapted{
-T adapter()
}
class SuspendForBody{
-T adapter()
}
class SuspendForResponse{
-T adapter()
}
结合类图在结合代码再来看下:
1 2 3 4 5 6 7 8 9 public <T> T create (final Class<T> service) { validateServiceInterface(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); } }); }
loadServiceMethod(method)方法就是去创建了ServiceMethod对象,它通过Method上面的注解判断这次的请求是协程呢还是Call呢还是其他,然后通过创建出对应的ServiceMethod对象,调用这个对象的invoke方法,通过上面的类图我们可以看到只有HttpServiceMethod类实现了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对象,然后调用adapter方法。通过类如可以看到实现adapter方法的类只有三个(哪三个,去看图)。
现在来看下loadServiceMethod是怎么通过注解来确定HttpServiceMethod具体是哪个对象的。
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; }
可以看到是调用了ServiceMethod.parseAnnotations()方法获取到具体的HttpServiceMethod对象。
1 2 3 4 5 6 7 8 9 10 abstract class ServiceMethod <T > { static <T> ServiceMethod<T> parseAnnotations (Retrofit retrofit, Method method) { RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method); Type returnType = method.getGenericReturnType(); return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory); } abstract @Nullable T invoke (Object[] args) ; }
这里通过RequestFactory方法将解析完的接口上面的全部注解信息全部保存在了内 RequestFactory类里面。
然后将我们解析完成的数据交给了HttpServiceMethod的parseAnnotations方法去继续执行。
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 static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations ( Retrofit retrofit, Method method, RequestFactory requestFactory) { 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(); } 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); } }
看上面的代码可以知道,首先判断是不是协程,是的话在判断是不是需要返回Response。如果需要的话标志参数continuationWantsResponse设置为true。如果是协程的话,会给我们的注解组数里面手动添加一个SkipCallbackExecutor的新注解,用来实现跳过手动执行call的调用网络请求的方法。
从可用工厂返回一个适合ResponseBody类型的转换器。
1 2 3 4 public <T> Converter<ResponseBody, T> responseBodyConverter (Type type, Annotation[] annotations) { return nextResponseBodyConverter(null , type, annotations); }
一个进行响应请求的适配器,他们的构造函数都需要:
RequestFactory requestfactory // 解析请求接口上面注解的所有数据
okhttp3.Call.Factory callFactory
Converter<ResponseBody,ResponseT> responseConverter // 适合ResponseBody的类型转换器
CallAdaper<ResponseT,ReturnT>callAdapeter
然后纯协程写的方法不带Response返回类型的还会在多一个参数 fasle
现在来一个一个介绍这几个参数都是在干嘛:
callFactory
他的获取方式是通过retrofit.callFactory
1 2 okhttp3.Call.Factory callFactory = retrofit.callFactory;
retrofit里面的callfactoty是什么时候创建的呢?
就是我们创建Retrofit对象的时候。也就是给Retrofit创建我们的OkhttpClient的时候就创建好了。
callAdapeter
通过遍历callAdapterFactories数组,通过reruenTyped来确定返回哪个CallAdaper
1 2 3 4 5 6 7 8 9 CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations); private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter ( Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) { return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations); } }
1 2 3 4 5 public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null , returnType, annotations); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { Objects.requireNonNull(returnType, "returnType == null" ); Objects.requireNonNull(annotations, "annotations == null" ); 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; } } }
在Retrofit里面看到了这个callAdapterFactories。。。。。问题又来了 这个是啥?
在Retrofit类里面提供了两个公开方法:
看名知意:addConverterfactory():添加网络请求回来的结果解析工厂,最常用的有:
1 addConverterFactory(GsonConverterFactory.create(new GsonBuilder().create()))
看名知意:addCallAdapterFactory():进行网络请求。常用的有支持RxJava的:
1 addCallAdapterFactory(RxJava2CallAdapterFactory.createAsync())
在上面创建callAdapter的时候传入一个叫adapterType的参数,那这个adapterType参数又是什么呢?
adapterType
这个adapterType是一个Type类型,也就是说他是一个泛型对象,在HttpSermethod他的创建分为两种,一种是基于kotlin协程创建的adapterType。一种是基于最基本的adapterType。
1 2 3 4 5 6 7 8 9 if (isKotlinSuspendFunction) { adapterType = new Utils.ParameterizedTypeImpl(null , Call.class, responseType); annotations = SkipCallbackExecutorImpl.ensurePresent(annotations); } else { adapterType = method.getGenericReturnType(); }
可以看到不是协程的话,那么adapterType就是获取我们方法返回的类型。如果是协程的话:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 static final class ParameterizedTypeImpl implements ParameterizedType { private final @Nullable Type ownerType; private final Type rawType; private final Type[] typeArguments; ParameterizedTypeImpl(@Nullable Type ownerType, Type rawType, Type... typeArguments) { if (rawType instanceof Class<?> && (ownerType == null ) != (((Class<?>) rawType).getEnclosingClass() == null )) { throw new IllegalArgumentException(); } for (Type typeArgument : typeArguments) { Objects.requireNonNull(typeArgument, "typeArgument == null" ); checkNotPrimitive(typeArgument); } this .ownerType = ownerType; this .rawType = rawType; this .typeArguments = typeArguments.clone(); } }
如是是协程的话,那么就创建一个type对象,他的rawType = retrofit2.Call。
callAdapter
现在我们再来分析下callAdapeter对象创建的时候,在Retrofit的nextCallAdapter是怎么创建的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { Objects.requireNonNull(returnType, "returnType == null" ); Objects.requireNonNull(annotations, "annotations == null" ); 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数组找出那个可以执行returnType的类。这个方法的第一行就可以看出,他上来就判断returnType是不是Call.class对象。现在就知道了为什么在使用协程的时候,需要自己构建一个returnType指定他的rawType为Call.class的原因了。
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 @Override public @Nullable CallAdapter<?, ?> get( Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null ; } if (!(returnType instanceof ParameterizedType)) { throw new IllegalArgumentException( "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>" ); } final Type responseType = Utils.getParameterUpperBound(0 , (ParameterizedType) returnType); final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : callbackExecutor; return new CallAdapter<Object, Call<?>>() { @Override public Type responseType () { return responseType; } @Override public Call<Object> adapt (Call<Object> call) { return executor == null ? call : new ExecutorCallbackCall<>(executor, call); } }; }
可以看到如果是协程的话,那么创建的callAdapter实际上是CallAdapter 通过匿名接口实现匿名内部类。
responseConverter
和callAdapter一样的设计思路。
到现在HttpServiceMethod对象已经创建完毕,现在我们继续跟进看是怎么调用的。
这里拿SuspendForBody这个HttpServiceMethod对象来举例:
1 2 3 4 new SuspendForBody<>(requestFactory, callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter, continuationBodyNullable);
首先调用他们的父类HttpServiceMethod的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); }
创建Call对象。然后执行了adapt方法。adapt方法是在HttpServiceMethod的子类实现的。所以现在回到SuspendForBofy类。:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 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); Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1 ]; try { return isNullable ? KotlinExtensions.awaitNullable(call, continuation) : KotlinExtensions.await(call, continuation); } catch (Exception e) { return KotlinExtensions.suspendAndThrow(e, continuation); } }
第一行出现了callAdapter,这个callAdapter也就是刚才我们讲的根据根据returnType去创建对应的callAdapter。对于协程来说创建的就是一个匿名接口实现的匿名内部类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 new CallAdapter<Object, Call<?>>() { @Override public Type responseType () { return responseType; } final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class) ? null : callbackExecutor; @Override public Call<Object> adapt (Call<Object> call) { return executor == null ? call : new ExecutorCallbackCall<>(executor, call); } };
call的获取过程现在知道了。
回到SuspendForBody的adapt方法:最后执行了kotlin写的扩展方法。执行了call的网络请求调用:
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 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); Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1 ]; try { return isNullable ? KotlinExtensions.awaitNullable(call, continuation) : KotlinExtensions.await(call, continuation); } catch (Exception e) { return KotlinExtensions.suspendAndThrow(e, continuation); } } }
关于协程里面一个请求是怎么发出去的,可以看到Retrofit对Call写了一个扩展方法,太秀了。~~~~
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) } }) } }