Retrofit 简单使用与源码结构

Retrofit 使用方法简介

       1.创建一个 interface 作为 Web Service 的请求集合,在里面用注解(Annotation)写入需要配置的请求方法:

1
2
3
4
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}

       2.在正式代码里用 Retrofit 创建出 interface 的实例:

1
2
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/").build();
GitHubService service = retrofit.create(GitHubService.class);

       3.调用创建出的 Service 实例的对应方法,创建出相应的可以用来发起网络请求的 Call 对象:

1
Call<List<Repo>> repos = service.listRepos("octocat");

       4.使用 Call.execute() 或者 Call.enqueue() 来发起请求:

1
repos.enqueue(callback);

Retrofit 源码结构总结

       Retrofit 版本为 com.squareup.retrofit2:retrofit:2.4.0

  • 通过 Retrofit.create(Class)方法创建出 Service interface 的实例,从而使得 Service 中配置的方法变得可用,这是 Retrofit 代码结构的核心;

  • Retrofit.create() 方法内部,使用的是 Proxy.newProxyInstance() 方法来创建 Service 实例。这个方法会为参数中的多个 interface (具体到 Retrofit 来说,是固定传入一个 interface )创建一个对象,这个对象实现了所有 interface 的每个方法,并且每个方法的实现都是雷同的:调用对象实例内部的一个 InvocationHandler 成员变量的 invoke() 方法,并把自己的方法信息传递进去。这样就在实质上实现了代理逻辑:interface 中的方法全部由一个另外设定的 InvocationHandler 对象来进行代理操作。并且,这些方法的具体实现是在运行时生成 interface 实例时才确定的,而不是在编译时(虽然在编译时就已经可以通过代码逻辑推断出来)。这就是网上所说的动态代理机制的具体含义。

  • 因此,invoke() 方法中的逻辑,就是 Retrofit 创建 Service 实例的关键。这个方法内有三行关键代码,共同组成了具体逻辑:

       1.ServiceMethod 的创建:

1
2
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);

       这行代码负责读取 interface 中原方法的信息(包括返回值类型、方法注解、参数类型、参数注解),并将这些信息做初步分析。

       2.OkHttpCall 的创建:

1
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);

       OkHttpCall 是 retrofit2.Call 的子类。这行代码负责将 ServiceMethod 封装进一个 retrofit2.Call 对象;而这个对象可以在需要的时候(例如它的 enqueue() 方法被调用的时候,利用 ServiceMethod 中包含的信息来创建一个 okhttp3.Call 对象,并调用这个 okhttp3.Call 对象来进行网络请求的发起,然后对结果进行预处理(如类型转换)。

       3.adapt() 方法:

1
return serviceMethod.adapt(okHttpCall);

       这个方法会使用 ServiceMethod 中的 callAdapter 对象来把 okHttpCall 对象进行转换,生成一个新的 retrofit2.Call 对象,在这个新的 Call 对象中,后台线程发起的请求,会在相应返回后,从主线程中调用回调方法,实现线程的自动切换。另外,这个方法不止可以生成新的 retrofit2.Call 对象,也可以生成别的类型对象,例如 RxJava 的 Observable ,来让 Retrofit 可以和 RxJava 结合使用。

参考资料:
腾讯课堂 HenCoder

Fork me on GitHub