0%

Retrofit分析

上篇Retrofit初探中已初步使用了Retrofit,简单介绍了Retrofit的使用步骤。本篇继续深入分析一下Retrofit流程。

Retrofit创建

先看一下Retrofit的创建

1
2
3
4
5
6
7
Retrofit 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
19
public 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
16
private 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 {
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}

@Override
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
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); //提交到主线程,起到切换线程的作用
}
}
}

在Android平台中defaultCallbackExecutor()方法返回的是一个线程池,在execute()中执行绑定MainLooper的Handler提交Runnable到主线程。

Retrofit请求的创建

在Volley中描述一个HTTP请求是需要创建一个Request对象,然后把这个请求对象放到一个队列中,让网络线程去处理。那Retrofit是怎么做的呢?

1
2
3
4
5
6
7
interface Api {
@GET("/repos/{owner}/{repo}/contributors")
Call<List<Contributor>> repoContributors(
@Path("owner") String owner,
@Path("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
25
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);
}
//对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 service)方法使用了 动态代理 来生成接口实现类。通过该函数,我们可以拿到一个前面自定义的Api的一个代理类,其功能就相当于一个Api对象,
即我们可以通它调用Api里的各个成员函数。其中最重要的三行代码为:

1
2
3
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);

第一行 loadServiceMethod(method):

1
2
3
4
5
6
7
8
9
10
11
ServiceMethod 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
15
public 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()
@Override
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<?>>() {
@Override public Type responseType() {
return responseType;
}

@Override 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
40
static 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;
}

@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("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();
}
}

至此,就把一个接口方法转换成ExecutorCallbackCall对象,ExecutorCallbackCall中execute()和enqueue()分别是同步和异步请求。在异步请求中通过callbackExecutor实现了线程切换,把请求结果发送到主线程。

本篇通过一个请求实例,浅显的了解了Retrofit中一步步代码执行顺序,尽管没有对Retrofit各个类和方法深入探究,但通过此次分析,相信对Retrofit基本步骤已经有了更深刻的了解。文中如有错误希望大家指出~下面一张福利是Stay大神画的Retrofit流程图:
Retrofit流程图

参考

Java 动态代理机制分析及扩展
Retrofit分析-漂亮的解耦套路

转载请注明出处:https://blog.lovek.vip/2016/05/03/retrofit-intro2

赞赏是最好的支持