Retrofit 是 square 推出用来请求 RESTful 风格 API 的网络库,可以让开发人员快速开发 RESTful 风格的应用。
本文基于 retrofit2.5.0
进行分析。
简单使用
我们先从官方的例子中了解一下怎么使用,相信对于 Android 开发者来说,使用已经非常熟练了。
1
2
3
4
5
6
7
8
9
10
11
|
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> repos = service.listRepos("octocat");
repos.execute();
|
例子中先创建了 API 接口,然后创建了 Retrofit 实例,接着调用 retrofit.create
创建了接口实现类,最后就是我们调用网络请求获取数据了。 retrofit
基本的用法就是这样。
下面我们就来一步一步分析
Retrofit.build
Retrofit
使用建造者模式创建 API,我们从 Retrofit.build
开始分析
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
|
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
// 设置 OkHttp
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 设置回调
callbackExecutor = platform.defaultCallbackExecutor();
}
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
// 添加适配器
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// 添加数据转换器
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
|
在创建 Retrofit
时,先设置了 callFactory
,如果没有手动设置,那么 Retrofit
默认会帮你设置为 OkHttpClient
。
接下来设置 callbackExecutor
,如果没有设置则会调用 platform
的 defaultCallbackExecutor
, platform
会根据不同的平台返回不同的 Executor
, Android
中返回的是 MainThreadExecutor
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
|
在 MainThreadExecutor
中看到 Callback
默认是在主线程的。顺便提一下 platform
是在 Builder
的构造方法中设置的,属于太细节,这里就不去分析了。
可以看到接下来设置的 defaultCallAdapterFactory
返回的是 ExecutorCallAdapterFactory
。
最后设置 converterFactories
,这是用来把服务器结果转换成我们期望的格式,通常我们会转换成 JSON
。 Retrofit
也内置了 BuiltInConverters
,它只能转换 Void
、 Buffer
、 Stream
类型。
总结一下 Retrofit#build
干了什么
callFactory
没有设置默认为 OkHttpClient
callbackExecutor
Android 平台默认是 MainThreadExecutor
,用来回调请求结果的。
callAdapterFactories
Android 平台默认添加 ExecutorCallAdapterFactory
,用来把 Retrofit.Call
转换成其他的 Call
这里其实是 OkHttpCall
。这样 Retrofit.Call
就和别的 Call
高度解耦了。
converterFactories
默认添加 BuiltInConverters
,用来把请求结果转换成对应的 JavaBean
Retrofit.create
Retrofit
的实例创建好了,需要调用 create
来创建接口的实现类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public <T> T create(final Class<T> 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 Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
|
在 create
方法中使用了动态代理创建接口的实现类,当我们调用接口中的方法会执行 invoke
,第一参数就是调用的对象,第二个参数就是调用对象的某个方法,第三个参数就是方法需要的参数。如果调用的类是 Object
和 Java8
的方法,则直接调用。最后返回 loadServiceMethod(method).invoke(args != null ? args : emptyArgs)
。
loadServiceMethod
接下来我们来看最有料的 loadServiceMethod
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
为了提高性能做了缓存,不然每次都要查找多费时间。最后调用 ServiceMethod.parseAnnotations
生成 ServiceMethod
并返回了。这样看来重点在 parseAnnotations
中,跟进去看看。
parseAnnotations
1
2
3
4
5
6
7
|
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// 省略一些检查判断...
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
|
首先调用了 RequestFactory.parseAnnotations
生成 RequestFactory
,在 RequestFactory.parseAnnotations
中会根据注解解析出请求方法,请求 URL
,请求头,请求体,表单等信息,代码如下。
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
|
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(Builder builder) {
method = builder.method;
baseUrl = builder.retrofit.baseUrl;
httpMethod = builder.httpMethod;
relativeUrl = builder.relativeUrl;
headers = builder.headers;
contentType = builder.contentType;
hasBody = builder.hasBody;
isFormEncoded = builder.isFormEncoded;
isMultipart = builder.isMultipart;
parameterHandlers = builder.parameterHandlers;
}
|
然后调用了 HttpServiceMethod.parseAnnotations
,生成 ServiceMethod
,接下来看一下 HttpServiceMethod.parseAnnotations
是怎么构建 ServiceMethod
的。
1
2
3
4
5
6
7
8
9
10
|
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
...
Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
|
HttpServiceMethod.parseAnnotations
先调用了 createCallAdapter
找到对应的 callAdapter
并取出返回值的类型,然后调用 createResponseConverter
把返回值类型传递进去,找到对应的 responseConverter
、最后把它们和 callFactory
、 requestFactory
封装成 serviceMethod
。
接下来看看 CallAdapter
和 responseConverter
是怎么被创建的
createCallAdapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(Retrofit retrofit, Method method) {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
// 省略部分代码
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
}
// Retrofit#callAdapter
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
// Retrofit#nextCallAdapter
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;
}
}
}
|
createCallAdapter
方法调最后调用的是 nextCallAdapter
,它会遍历 callAdapterFactories
根据注解和返回值类型查找合适的 CallAdapter
。在构造 Retrofit
时,我们可以通过 addCallAdapterFactory
往 callAdapterFactories
添加需要的适配器。
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
29
30
31
32
|
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);
}
}
// Retrofit#responseBodyConverter
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
// Retrofit#nextResponseBodyConverter
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;
}
}
// ....
}
|
和 createCallAdapter
一样的套路,遍历 converterFactories
根据注解和返回值类型查找合适的 Converter
。
loadServiceMethod
做的就是通过返回值和注解生成 CallAdapter
和 ResponseConverter
,最后构造 HttpServiceMethod
。
invoke
loadServiceMethod
最后返回的是 HttpServiceMethod
,所以最后调用的 invoke
,是 HttpServiceMethod
的 invoke
。
1
2
3
4
5
|
// HttpServiceMethod
@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
|
invoke
调用了 callAdapter.adapt
,根据之前的分析知道默认的 callAdapterFactories
是 ExecutorCallAdapterFactory
, 所以这里的 callAdapter
是 ExecutorCallAdapterFactory
中返回的匿名的 CallAdapter
。代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
|
在 adapt
方法中返回了 ExecutorCallbackCall
所以调用接口的方法最后返回的是 ExecutorCallbackCall
,也就是我们调用 Retrofit.create
创建的服务,调用其中的方法,最后面其实调用 ExecutorCallbackCall
。 关于 ExecutorCallbackCall
我们后面还会碰到。
小节一下 Retrofit#create
里做了这么几件事
- 根据动态代理为每个接口方法创建
ServiceMethod
- 在
loadServiceMethod
中根据注解和方法的返回值的类型,生成 requestFactory
- 在
HttpServiceMethod.parseAnnotations
中根据注解寻找合适的 CallAdapter
和 ResponseConverter
。构建 ServiceMethod(HttpServiceMethod)
。
- 在
HttpServiceMethod#invoke
中调用 callAdapter.adapt
把 Retrofit.Call
适配成 callFactory
能调用的请求,也就是 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
|
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
|
在上小节中,调用 invoke
最后得到的是一个 ExecutorCallbackCall
,其中 delegate
是个 OkHttpCall
我们调用 enqueue
其实调用的是 OkHttpCall
的 enqueue
, execute
直接调用了 delegate.execute()
,就不说了。
来看 enqueue
的 onResponse
中,最后的的结果会调用 callbackExecutor.execute
,之前我们分析在 Android
中 这个 callbackExecutor
是 MainThreadExecutor
,所以最后的结果是在主线程中被回调的。
OkHttpCall
接下来我们来看看 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
37
38
39
40
41
42
43
44
45
46
47
48
49
|
@Override public void enqueue(final Callback<T> callback) {
// ...
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
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) {
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) {
t.printStackTrace();
}
}
});
}
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;
}
|
enqueue
中先调用了 createRawCall
,而 createRawCall
中调用了 callFactory.newCall
,所以最后是调用了 OkHttpClient
的 newCall
来创建 OkHttp
的 Call
。 而 requestFactory.create
来创建 okhttp
的 Request
。这样就把网络请求交给了 OkHttp
。
解析请求结果
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
// ...
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;
}
}
|
在 OkHttpCall
中请求成功后,会调用 parseResponse
来把服务返回的数据转换成对应的 JavaBean
。 而实际进行转换的是 responseBodyConverter.convert
。
总结
Retrofit
通过动态代理创建 API 的实现类。
- 通过
callAdapter
进行请求的转换。把 Retrofit.Call
适配成 OkHttpCall
- 通过
responseConverter
进行请求结果的转换。
- 具体的网络请求交给
callFactory
。
- 通过
callbackExecutor
把请求的结果往主线程切换。
- 通过注解生成
request
总体上讲 Retrofit
实际是对网络框架的一层封装,让其更方便的处理 RESTful
风格的 API。
参考
Retrofit 分析-漂亮的解耦套路
拆轮子系列:拆 Retrofit
Retrofit 源码解析