上篇Retrofit初探中已初步使用了Retrofit,简单介绍了Retrofit的使用步骤。本篇继续深入分析一下Retrofit流程。
Retrofit创建
先看一下Retrofit的创建1
2
3
4
5
6
7Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
//手动指定Fastjson解析方式,可指定不同Convert来使用如Gson,Jackson,XML等解析方式
.addConverterFactory(FastjsonConverterFactory.create())
//返回数据为RxJava形式
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
可以看出Retrofit对象是通过Builder来创建,构建器很方便我们设置Retrofit需要的属性。通过build()方法就创建了一个Retrofit对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public Retrofit build() {
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
如果我们没有指定一个client或者callFactory,Retrofit2中默认生成一个OkHttpClient。然后通过platform.defaultCallbackExecutor()实例化一个Executor的对象callbackExecutor。Converter是数据转换器,该接口将Http请求返回的数据解析成Java对象,
addConverterFactory(FastjsonConverterFactory.create())添加一个FastjsonConverter来使用Fastjson来将我们的结果转化成Model类。CallAdapter是Call的适配器,负责将Call对象转化成另一个对象,同样在创建Retrofit实例时调用addCallAdapterFactory(Factory)来添加。
这样一个Retrofit的实例就创建完成了。其中platform是Builder进行初始化的时候调用了Platform.get()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
//...省略部分代码...
return new Platform();
}
使用了单例的PLATFORM,通过findPlatform()初始化实例,如果是Android平台就实例化一个Android对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 static class Android extends Platform {
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
public void execute(Runnable r) {
handler.post(r); //提交到主线程,起到切换线程的作用
}
}
}
在Android平台中defaultCallbackExecutor()方法返回的是一个线程池,在execute()中执行绑定MainLooper的Handler提交Runnable到主线程。
Retrofit请求的创建
在Volley中描述一个HTTP请求是需要创建一个Request对象,然后把这个请求对象放到一个队列中,让网络线程去处理。那Retrofit是怎么做的呢?1
2
3
4
5
6
7interface Api {
"/repos/{owner}/{repo}/contributors") (
Call<List<Contributor>> repoContributors(
"owner") String owner, (
"repo") String repo); (
}
Api api = retrofit.create(Api.class);
声明一个Api的接口,给Retrofit对象传了一个Api接口的Class对象,怎么又返回一个Api对象呢?进入create方法看一下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public <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();
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);
}
//对java8的兼容
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
create(final Class
即我们可以通它调用Api里的各个成员函数。其中最重要的三行代码为:
1 | ServiceMethod serviceMethod = loadServiceMethod(method); |
第一行 loadServiceMethod(method):1
2
3
4
5
6
7
8
9
10
11ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
该方法会根据接口请求方法method来建造一个ServiceMethod,ServiceMethod是将一个接口方法适配成一个Http call。Retrofit会维护一个serviceMethodCache缓存,如果已经构建的ServiceMethod直接从缓存里取到并返回。
否则构建一个新的ServiceMethod对象,并放入缓存中。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public ServiceMethod build() {
callAdapter = createCallAdapter(); //这个CallAdapter就是 retrofit.callAdapter()
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter(); //retrofit.responseBodyConverter()
//解析@GET @POST等注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//...省略...
}
在构建ServiceMethod时,会调用createCallAdapter()来为ServiceMethod添加一个CallAdapter,此实例中这里的CallAdapter是默认的ExecutorCallAdapterFactory。
再回到invoke()最后一行,Retrofit默认实现是OkHttpCall。1
return serviceMethod.callAdapter.adapt(okHttpCall);
通过CallAdapter适配后,动态代理返回的是ExecutorCallbackCall,一个真正实现了Call接口的实例。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//ExecutorCallAdapterFactory.get()
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
public Type responseType() {
return responseType;
}
public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, 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
33
34
35
36
37
38
39
40static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");
delegate.enqueue(new Callback<T>() {
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
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);
}
}
});
}
public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
public Response<T> execute() throws IOException {
return delegate.execute();
}
}
至此,就把一个接口方法转换成ExecutorCallbackCall对象,ExecutorCallbackCall中execute()和enqueue()分别是同步和异步请求。在异步请求中通过callbackExecutor实现了线程切换,把请求结果发送到主线程。
本篇通过一个请求实例,浅显的了解了Retrofit中一步步代码执行顺序,尽管没有对Retrofit各个类和方法深入探究,但通过此次分析,相信对Retrofit基本步骤已经有了更深刻的了解。文中如有错误希望大家指出~下面一张福利是Stay大神画的Retrofit流程图: