源码分析-Retrofit

一、Retrofit的大致使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface ZhihuService {
/**
* 获取消息具体内容
* @param new_id 消息对应ID
* @return
*/
@GET("api/4/news/{new_id}")
Observable<NewsDetailInfo> getNewsDetail(@Path("new_id") String new_id);
}
public static final String API_URL = "http://news-at.zhihu.com/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.client(mOkHttpClient)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofit.create(ZhihuService.class)
.getNewsDetail("19")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe();

二、Retrofit的工作原理

从使用上看,Retrofit就是充当了一个适配器(Adapter)的角色:将一个Java接口翻译成一个Http请求,然后用OkHttp去发送这个请求。其中,翻译的过程是通过Java的动态代理完成的。

三、源码分析

(一)动态代理类的创建过程
1
RxHttpService apiService = retrofit.create(RxHttpService.class);
1)Retrofit#create:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
@Override public Object invoke(Object proxy, Method method, 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)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadMethodHandler(method).invoke(args);
}
});
}

在这里创建了动态代理类Proxy.newProxyInstance并返回了一个RxHttpService接口对象,当后面service执行方法时,将被动态代理拦截,进入newProxyInstance()方法内部,里面创建了一个InvocationHandler类。InvocationHandler类是代理类和委托类之间的中间类,主要工作是:

1
loadMethodHandler(method).invoke(args);
2)Retrofit#loadMethodHandler:
1
2
3
4
5
6
7
8
9
10
11
MethodHandler loadMethodHandler(Method method) {
MethodHandler handler;
synchronized (methodHandlerCache) {
handler = methodHandlerCache.get(method);
if (handler == null) {
handler = MethodHandler.create(this, method);
methodHandlerCache.put(method, handler);
}
}
return handler;
}

Retrofit内部维护了一个method对应的Map表,这里将每一个method都封装成MethodHandler类(委托类),再将method和MethodHandler作为键值对存入Map表;所以调用代理类Proxy,实际上就是调用委托类MethodHandler的invoke,具体的实现逻辑都在MethodHandler中。

(二)委托类MethodHandler的具体工作
1)MethodHandler类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static MethodHandler create(Retrofit retrofit, Method method) {
CallAdapter<?> callAdapter = createCallAdapter(method, retrofit);
Type responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw Utils.methodError(method, "'"
+ Types.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
Converter<ResponseBody, ?> responseConverter =
createResponseConverter(method, retrofit, responseType);
RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
return new MethodHandler(retrofit.callFactory(), requestFactory, callAdapter,
responseConverter);
}

MethodHandler是系统为定义的Service接口中的每一个method创建的一个具体执行类,通过调用其invoke函数,来执行具体的请求逻辑。在create()中主要做三件事:

  • createCallAdapter():在retrofit中找到一个合适的callAdapter。
  • createResponseConverter():在retrofit中找到一个合适的ResponseConverter。
  • RequestFactoryParser.parse():通过解析返回类型和method的对应注解获得主要的请求信息。

MethodHandler主要包含四个变量:

1
2
3
4
5
6
private MethodHandler(okhttp3.Call.Factory callFactory, RequestFactory requestFactory, CallAdapter<?> callAdapter, Converter<ResponseBody, ?> responseConverter) {
this.callFactory = callFactory;
this.requestFactory = requestFactory;
this.callAdapter = callAdapter;
this.responseConverter = responseConverter;
}

Call.Factory:————就是OkHttpClient

RequestFactory:包含了HTTP请求的Url、Header信息、MediaType、Method以及RequestAction数组

CallAdapter:HTTP请求返回数据的类型

ResponseConverter:对返回数据进行转换的类型转换器

接下来具体看每个变量的创建:

2)Retrofit#callAdapter

在MethodHandler#create中直接通过createCallAdapter()创建一个CallAdapter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static CallAdapter<?> createCallAdapter(Method method, Retrofit retrofit) {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw Utils.methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw Utils.methodError(method, "Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw Utils.methodError(e, method, "Unable to create call adapter for %s", returnType);
}
}

但实际上createCallAdapter()内部是调用Retrofit#callAdapter并传入method的注解创建CallAdapter的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
......
// 找不到adapter,抛出异常
}

adapterFactorie是Retrofit上的一个链表,保存了所有的CallAdapter.Factory,通过遍历获取相应的CallAdapter。而在我们创建Retrofit的时候呢,写过

1
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())

由此,我们可以在最外层定义我们需要的CallAdapterFactory,否则将加载系统默认的CallAdapterFactory。

3)Retrofit#responseBodyConverter

在MethodHandler#create中通过createResponseConverter()获取一个ResponseConverter,但实际上也是通过Retrofit实现的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
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;
}
}
......
// 找不到ResponseBodyConverter,抛出异常
}

Retrofit内同样维护了一个converterFactories的链表,保存了所有的Converter.Factory,通过responseType和method的注解(annotations)获取链表中符合条件的ResponseConverter。而我们在创建Retrofit的时候,设置了

1
.addConverterFactory(GsonConverterFactory.create())

由此,加载了GsonConverterFactory这个响应体的转换器,通过responseType找到response对应的Object,再使用annotations对该Object进行校验,返回合适的ResponseConverter。

4)RequestFactory

我们知道,RxHttpService的每一个method对应的主要请求信息都在method对应的注解上,而RequestFactoryParser就是根据method对应的注解及返回类型进行相应解析,并将解析出的信息都保存在一个RequestFactory中,好让OkHttpCall正式发起访问时再将RequestFactory整合成一个Request。

1
RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
final class RequestFactoryParser {
private final Method method;
static RequestFactory parse(Method method, Type responseType, Retrofit retrofit) {
RequestFactoryParser parser = new RequestFactoryParser(method);
// Method对应的注解这里解析
parser.parseMethodAnnotations(responseType);
parser.parseParameters(retrofit);
// 创建一个RequestFactory
return parser.toRequestFactory(retrofit.baseUrl());
}
private RequestFactoryParser(Method method) {
this.method = method;
}
}

解析的主要工作由parseMethodAnnotations(responseType)和parsePameters(retrofit)完成。最后通过toRequestFactory()使用创造者模式创建一个RequestFactory对象,包含method、url、headers、contentType、其他表单信息等内容。

5)MethodHandler#invoke
1
2
3
4
Object invoke(Object... args) {
return callAdapter.adapt(
new OkHttpCall<>(callFactory, requestFactory, args, responseConverter));
}

动态代理创建的代理类使用InvokeHandler调用委托类的invoke来实现一个具体的方法。而委托类是系统根据method创建的MethodHandler,在创建过程中会通过Retrofit获取对应callAdapter和responseConverter的引用,并通过解析responseType和method对应的注解创建一个RequestFactory。在委托类MethodHandler调用自身的invoke函数后,invoke又继续调用callAdapter#adapt函数,生成一个OkHttpCall对象。OkHttpCall是对OkHttp里面的Call的封装,将所有的操作都委托给该Call进行操作,获取响应后OkHttp.Call由将结果传回给OkHttpCall,OkHttpCall使用responseConverter.convert()将结果转化成对应对象,在通过Callback将结果对象和结果一并传到最外层,交给我们使用。

6)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
33
34
35
36
private okhttp3.Call rawCall;
@Override
public void enqueue(final Callback<T> callback) {
......
call = rawCall = createRawCall(); // 创建OkHttp.Call
......
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
// OkHttp.Call传回响应结果,使用responseConverter将结果转为对象
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callback.onFailure(OkHttpCall.this, e);
}
private void callFailure(Throwable e) {
callback.onFailure(OkHttpCall.this, e);
}
private void callSuccess(Response<T> response) {
callback.onResponse(OkHttpCall.this, response);
}
});// end for enqueue()
}

这里主要方法是createRawCall()、call.enqueue()和parseResponse()。

1
2
3
4
5
6
7
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}

首先requestFactory根据args参数创建一个Request,然后okHttpClient再根据request创建一个call。注意,这里的callFactory其实就是OkHttpClient,在创建Retrofit的时候,我们设置过

1
.client(mOkHttpClient)

再看Retrofit#client方法:

1
2
3
4
5
6
7
8
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}

至此,OkHttp.Call已经创建完成了,在后面call.enqueue()就是由OkHttp去完成网络请求,然后通过OkHttp的回调Callback#onResponse得到响应后通过parseResponse()将结果转为对象,再通过OkHttpCall的回调Callback将结果对象和结果一并传到最上层。

OkHttpCall#execute过程同理。