Retrofit
Retrofit 是一个 RESTful 的 HTTP 网络框架封装,底层使用的 OkHttp.
基本使用
引入依赖
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
创建一个接口作为网络的请求集合,在方法上用注解进行配置
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
使用 Retrofit 创建出接口的实例
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
调用接口的对应方法,就创建网络请求对象 Call
Call<List<Repo>> repos = service.listRepos("octocat");
使用 Call.enqueue() 或 Call.execute() 发起网络请求
repos.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
Log.e("TAG", "onResponse:" + response.body().get(0).getName());
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
}
});
源码分析
Retrofit 实例创建
Retrofit 实例是通过建造者模式创建的
// Retrofit类
public final class Retrofit {
// 网络请求配置对象(对接口中的方法注解解析后得到的对象)
// 缓存,存储网络请求中的相关配置,请求的方法,数据转换器,适配器,基地址
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;// 网络请求器的工厂
final HttpUrl baseUrl;
final List<Converter.Factory> converterFactories;// 数据转换器工厂集合
final List<CallAdapter.Factory> callAdapterFactories;// 网络请求适配器工厂集合
final @Nullable Executor callbackExecutor;// 回调方法执行器
final boolean validateEagerly;// 是否提前对接口中的方法注解进行验证
Retrofit(
okhttp3.Call.Factory callFactory,
HttpUrl baseUrl,
List<Converter.Factory> converterFactories,
List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor,
boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
...
// Builder类
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private @Nullable HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;// 平台类型对象
}
public Builder() {
this(Platform.get());
}
// 添加url地址
public Builder baseUrl(URL baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl.toString()));
}
// 添加数据转化器,可以把返回的数据解析成指定的类型
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
// 添加网络请求适配器,CallAdatper对原始Call进行再次封装,如Call<R>到Observable<R>
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
...
public Retrofit build() {
...
okhttp3.Call.Factory callFactory = this.callFactory;// 网络请求执行器
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// 如果没指定,则默认使用Platform检测环境时的默认callbackExecutor
// 即Android默认的callbackExecutor
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());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(
callFactory,
baseUrl,
unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories),
callbackExecutor,
validateEagerly);
}
}
}
平台类型 Platform
// Platform 类型
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
return "Dalvik".equals(System.getProperty("java.vm.name"))
? new Android() //
: new Platform(true);
}
...
// 用于接收服务器返回数据后进行线程切换在主线程显示结果
static final class Android extends Platform {
Android() {
super(Build.VERSION.SDK_INT >= 24);
}
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
// 回调方法执行器
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
}
}
数据转换器工厂 GsonConverterFactory
// GsonConverterFactory.crate() 创建了一个含有 Gson 对象实例
public final class GsonConverterFactory extends Converter.Factory {
public static GsonConverterFactory create() {
return create(new Gson());
}
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
...
}
Retrofit 使用建造者模式通过 Builder 类创建了一个 Retrofit 对象,配置了:
- 平台类型对象 (Platform)
- url地址(baseUrl)
- 网络请求工厂(callFactory)
- 网络请求适配器的集合(adpterFactories)
- 数据转换器工厂集合(converterFactories)
- 回调方法执行器(callbackExector)
请求接口实例创建
Retrofit 是通过 外观模式 和 代理模式 使用 Retrofit.create() 方法创建的网络请求接口的实例,从而使得接口 中配置的方法变得可用,这是 Retrofit 代码接口的核心。
外观模式:定义一个统一的接口,外部通过该接口对子系统里的其他接口进行访问
代理模式:通过访问代理对象的方式间接访问目标对象
Retrofit.create() 方法内部,使用的是 Proxy.newProxyInstance() 方法来创建 接口 的实例。这个方法内部会为入参的多个 inteface 创建了一个对象,这个对象实现了所有 interface 的每个方法,并且每个方法的实现都是雷同的:调用对象实例内部的一个 InvocationHandler 成员变量的 invoke() 方法,并把对应的方法信息传递进去。
因此 InvocationHandler 中的 invoke() 方法中的逻辑,就是执行接口中的方法。
// Retrofit类
public <T> T create(final Class<T> service) {
validateServiceInterface(service);// 验证接口
return (T)
// 创建了网络请求接口的动态代理对象
Proxy.newProxyInstance(
service.getClassLoader(),// 类加载器
new Class<?>[] {service},// 要创建哪些接口
new InvocationHandler() {// 当接口的方法触发,会间接调用到 InvocationHandler 的 invoke 方法
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override
public @Nullable Object invoke(Object proxy, Method method, @Nullable 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);// 如果是Object类,直接触发方法
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)// 平台默认方法,直接触发方法
: loadServiceMethod(method).invoke(args);// 核心是这行代码,加载接口的方法,并执行
}
});
}
ServiceMethod 的创建
loadServiceMethod(method),这行代码负责读取接口中原方法的信息(包括返回值类型、方法注解、参数类型、参数注解),并把这些信息做初步分析,最后实际返回的是一个 CallAdapted .
// Retrofit类
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;
}
// ServiceMethod类
// ServiceMethod.parseAnnotations
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 解析方法上的注解
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
method,
"Method return type must not include a type variable or wildcard: %s",
returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);// 关键是这句
}
abstract @Nullable T invoke(Object[] args);
}
// HttpServiceMethod类
// HttpServiceMethod.parseAnnotations
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
...
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
...
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);// 关键是这句
} else if (continuationWantsResponse) {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForResponse<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
} else {
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod<ResponseT, ReturnT>)
new SuspendForBody<>(
requestFactory,
callFactory,
responseConverter,
(CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
continuationBodyNullable);
}
}
OkHttpCall 的创建
invoke(args) 方法的调用,会触发 OkHttpCall 的创建。
// HttpServiceMethod类
@Override
final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);// 会调用到 CallApter 的 adapter 方法
}
OkHttpCall 是 retrofit2.Call 的子类,OkHttpCall 的创建将 ServiceMethod 解读到信息(RequestFactory、OkHttpClient 和 ResponseConverter)封装进 OkHttpCall,OkHttpCall 在 enqueue() 方法被调用的时候,利用 RequestFactory 和 OkHttpClient 来创建一个 okhttp3.Call 对象,并调用 okhttp3.Call 来进行网络请求的发起,然后利用 ResponseConverter 对结果进行预处理之后,交回给 Retrofit 的 Callback .
适配器的处理
adapt(call, args) 方法调用会触发到 callAdapter.adapt(call) 的调用
callAdapter.adapt(call);
这个⽅法会使⽤⼀个 CallAdapter 对象来把 OkHttpCall 对象进⾏转换,⽣成⼀个新的对象。默认情况下,返回的是⼀个 ExecutorCallbackCall,它的作⽤是把操作切回主线程后再交给 Callback .
如果有自定义的 CallAdapter,这里也可以生成别的类型的对象,例如 RxJava 的 Observable,来让 Retrofit 和 RxJava 结合使用。