Retrofit源码解析

在阅读源码的时候,里面大量使用到了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();//这个方法的参数的所有注解信息
}
}
}
/**
* 以上面ApiSerice这个接口为例子:
* this.methodAnnotations = [@retrofit2.http.Get(value=),@retrofit2.http.Streaming()]
* this.parameterTYpes = [String,Continuation<Response<REsponseBody>>]
* this.parameterAnnotationsArray = [@retrofit2.http.Url()]
*/

关于方法的注解解析都在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
// Retrofit.java
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
// HttpSercieMethod.java
@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) {
// Unwrap the actual body type from Response<T>.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
}

adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);// 这一步就是自动往我们的注解数组里面手动调价一个SkipCallbackExecutor的注解,用来实现跳过手动执行call.execu的方法。
} else {
adapterType = method.getGenericReturnType();// 获取方法的返回值类型。
}

// 返回正真的HttpServiceMethod对象
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
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);
}
}

  看上面的代码可以知道,首先判断是不是协程,是的话在判断是不是需要返回Response。如果需要的话标志参数continuationWantsResponse设置为true。如果是协程的话,会给我们的注解组数里面手动添加一个SkipCallbackExecutor的新注解,用来实现跳过手动执行call的调用网络请求的方法。

从可用工厂返回一个适合ResponseBody类型的转换器。

1
2
3
4
// Retrofit.java
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
//HttpSerciceMethod.java
okhttp3.Call.Factory callFactory = retrofit.callFactory;

    retrofit里面的callfactoty是什么时候创建的呢?

就是我们创建Retrofit对象的时候。也就是给Retrofit创建我们的OkhttpClient的时候就创建好了。

callAdapeter

    通过遍历callAdapterFactories数组,通过reruenTyped来确定返回哪个CallAdaper

1
2
3
4
5
6
7
8
9
// HttpSerciveMethod.java
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
// HttpServicemethod.java
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

// Retrofit.java
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
// Retrofit.java
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(Converter.Factory factory)

  • addCallAdapterFactory(CallAdapter.Factory factory)

看名知意: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 {
// getGenericReturnType();用来返回一个方法的返回具体类型。
adapterType = method.getGenericReturnType();
// 比如 Call<String> getName();
// 那么这时候的adapterType就是Call<String>
}

   可以看到不是协程的话,那么adapterType就是获取我们方法返回的类型。如果是协程的话:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Utils.java
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) {
// Require an owner type if the raw type needs it.
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
// Retrofit.java
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
// DefaultCallAdapterFactory.java
@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
// HttpServiceMethod.java
new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);

首先调用他们的父类HttpServiceMethod的invoke方法:

1
2
3
4
5
// HttpServiceMethod
@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.java
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);//对于协程这个callAdappter就是上面讲了创建了一个匿名接口的匿名内部类。

//noinspection unchecked Checked by reflection inside RequestFactory.
Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];
// 获取最后一个参数信息。
// 我们使用 suspend fun getMyName() 的时候经过编译后,这个suspend就被编译成了Continuation这个对象。也就是说这个方法实际上就是 Continuation fun getMyName();
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;
// 这个executor为null。因为在解析方法的时候,他判断了这个方法是不是协程,是的话就会代码里面自动给他添加上一个SkipCallbackExecutor的注释,意思就是告诉程序,协程的网络请求又程序自动进行。所以在调用adapt方法的时候返回的是call
@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
// HttpServiceMethod 
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)
}
})
}
}