Retrofit 依赖
// 添加依赖
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
Retrofit 的简单使用
本篇博客直接使用官方的示例,来获取 octocat
账户下第一个仓库的名称。
// 定义一个接口
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")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService gitHubApi = retrofit.create(GitHubService.class);
Call<List<Repo>> call = gitHubApi.listRepos("octocat");
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
mContentTextView.setText(response.body().get(0).getName() + " ");
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
Log.e(TAG, "onFailure: " + t.toString());
}
});
Retrofit 源码解析
源码查看原则,最近原则和只看我们关心的,那么就从 call.enqueue()
看起,发现是一个接口定义的方法,暂时放弃,往上看 GitHubService gitHubApi = retrofit.create(GitHubService.class);
retrofit 是怎么将一个接口转化为实现类的。
public interface Call<T> extends Cloneable {
// ******
void enqueue(Callback<T> callback);
}
// Retrofit#create()
public <T> T create(final Class<T> service) {
// 校验:API 方法的声明必须声明在接口里边,并且该接口不能有父接口
Utils.validateServiceInterface(service);
if (validateEagerly) { //激进的验证方式,一般不这么用
eagerlyValidateMethods(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 @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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
这是一个动态代理,这里代理的是 GitHubService
中定义的 API方法,其中 invoke()
方法也是抽象类 ServiceMethod<T> 中的抽象方法,等下贴出,那我们只能查看 invoke 调用处 loadServiceMethod(method)
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;
}
这里用到了缓存,默认缓存中是没有的,解析注解之后重新放到了缓存中,重点是怎么解析注解的,来一块看看;是一个单独的抽象类,invoke() 抽象方法也在其中。
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
// 这个 RequestFactory 里边存放的是:1.我们在 API 接口里边定义的方法的全部信息,包括方法的返回值,
// 方法的参数和方法的注解信息; 2.通过 Builder 模式构造Retrofit实例时,组装的参数,如 baseUrl 信息等
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
// ******
// HttpServiceMethod.parseAnnotations()调用的是一个静态方法,该方法返回值是 ServiceMethod<T>,
// 由下一步的查看源码可以知道,HttpServiceMethod 是 ServiceMethod 的实现类
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
// RequestFactory 解析在接口中定义的方法
// RequestFactory#parseAnnotations(retrofit, method)
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
// 该例子中解析的是 GithubService 接口中每个方法的信息
// 解析内容包括: 请求方法 httpMethod,请求相对path,Headers注解,是否标记Multipart 和 FormUrlEncoded注解等等
parseMethodAnnotation(annotation);
}
// ...省略一些校验...
return new RequestFactory(this);
}
// RequestFactory里边大概组装的信息有这些,不在啰嗦解析过程了
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;
isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
}
到这里我们捋一捋流程,我们查看动态代理里边的 invoke()
方法,发现是抽象泛型类 ServiceMethod
的一个抽象方法;然后我们查看了 invoke() 被调用的地方,通过跟进,最终调用方是HttpServiceMethod
,HttpServiceMethod
是ServiceMethod.parseAnnotations()
方法的返回值,到这里明白了动态代理里边的 invoke() 实际上走的是 HttpServiceMethod 类的 invoke() 方法。
/** Adapts an invocation of an interface method into an HTTP call. */
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
// ....
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
// ***
}
// 这里通过 requestFactory,args,callFactory,和 responseConverter 几个参数,创建了一个新的 OkHttpCall,
// 至于上边几个参数什么意思,等下就会分析到
// 最终 invoke() 调用抽象方法 adapt(),其中 call 就是创建的 OkHttpCall,我们只要找到 adapt() 的实现的地方即可,这里暂且放下
有一行代码还没看 return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
来分析一下:
// HttpServiceMethod#ParseAnnotations() 经过精简后的代码
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {
// ******
} else {
adapterType = method.getGenericReturnType();
}
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
// ******
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
// ******
// 注意这个返回值CallAdapted,是 HttpServiceMethod 的一个实现类,其实是 HttpServiceMethod 的一个静态内部类,
// 那么经过上面的分析,自然最终是调用到了 CallAdapted类的 adapt()方法里边去了
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
// ******
static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
private final CallAdapter<ResponseT, ReturnT> callAdapter;
CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter,
CallAdapter<ResponseT, ReturnT> callAdapter) {
super(requestFactory, callFactory, responseConverter);
this.callAdapter = callAdapter;
}
@Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
return callAdapter.adapt(call); // 最终调用了 CallAdapter.adapt()方法,回过头来分析 callAdapter 是什么
}
}
}
CallAdapted 实例化时参数分析
也即是 return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
中的各个参数,是什么?怎么来的?
- requestFactory 是什么
- callFactory 是什么
- responseConverter 是什么
- callAdapter 是什么
其中我们已经分析过 requestFactory
了,就是 API接口中定义的方法的解析类,做了一层封装;看下 callFactory 是什么?是在 Retrofit.java类中做的声明 okhttp3.Call.Factory callFactory
,其实就是 OkHttpClient 。
// callFactory 是在 Retrofit$Builder.build() 静态内部类 Builder 的一个 build()方法里边赋值操作的,callFactory其实就是OkhttpClient
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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
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);
}
responseConverter
是什么呢?经过追踪是从 converterFactories 集合
里边取得,而这个集合的赋值操作也在上面这个 build() 方法里边,是一些内置的转换工厂,还有一个是我们在实例化 Retrofit 时添加的自己的 ConverterFactory。
// 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;
}
}
// ******
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create()) //将响应数据,转化为对应的bean的转化工厂
.build();
现在就剩下 callAdapter
不知道是什么了,我们重点分析一下
Type adapterType = method.getGenericReturnType();
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, 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;
}
}
// ******
}
callAdapter 从集合 callAdapterFactories
中存储的CallAdapter.Factory
中取出来的,该集合也是在 build()中进行初始化的
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> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
Platform 该类是与平台相关的,内部有两个实现类 Java8
和 Android
,先看下 callbackExecutor 在 Android 里边的实现为:
// Platform$Android
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
// Platform$Android$MainThreadExecutor
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
callbackExecutor 是一个线程的管理类,工作在主线程。
platform.defaultCallAdapterFactories(callbackExecutor) 的实现主要在 DefaultCallAdapterFactory.java
类的 get() 方法里边。
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
// 这个 executor 取值为 callbackExecutor
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
// ******
}
到这里我们算是找到底了,callAdapter 的实例,最终是在 DefaultCallAdapterFactory类的 get()方法
创建出来的,也即是上面分析的 adapt() 抽象方法的实现。这个地方有点绕,现在问题转化为只需要分析 new ExecutorCallbackCall<>(executor, call)
这么一行代码了。
先简单说明一下四个参数的意义,再往下进行:
- requestFactory 是定义的 API 接口中方法的解析类
- callFactory 其实就是 OkHttpClient 对象
- responseConverter 是我们在构建 Retrofit 实例时,添加的转化工厂(暂不考虑 Retrofit 内置的转化工程类)
- callAdapter 是将一个 Call对象(OkhttpCall) 适配成 okhttp3.Call 的一个适配器
重点分析 new ExecutorCallbackCall<>(executor, call),其中的 call 为 OkhttpCall,executor 是一个线程管理类,工作在主线程。
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
// ******
static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate; // 这个 delegate 实际上已经是 okhttp3.Call 了
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) {
// 注意这里,切到了主线程,然后把结果通过 callback 给回调到了外面,所以我们在外边写回调的时候,不用切线程,直接就更新 UI 了
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 boolean isExecuted() {
return delegate.isExecuted();
}
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
// ***省略一些取消和请求的方法***
}
}
当我们在外部调用 call.enqueue(**new** Callback<List<Repo>>() {***});
时,就会走 delegate.enqueue() 方法,切换到主线程之后再回调给外部的 callback,这个 delegate 其实就是 OkHttpCall,是在 HttpServiceMethod.invoke() 方法中实例化的。
再说一句,这个 OkHttpCall 内部维护了一个 okhttp3.Call
,是在调用 delegate.enqueue() 的时候,通过 createRawCall()
来实例化的。由于 okhttp3.call请求是在子线程,所以 Retrofit 在内部帮我们把网络请求的响应结果切到了主线程,返回给了我们。
小总结吧:动态代理里边 invoke() 方法我的理解是,把 Retrofit 请求交给 invoke() 内部 adapt() 方法,将一个 Retrofit 类型的 Call 转变成了 okhttp3.Call对像,真正做事情的还是 okhttp。在响应数据返回的时候,retrofit 帮我们做了线程的切换。好了,Retrofit 的原理分析到此也就结束了,有些地方一点即过,可以去跟着翻翻源码。
网友评论