本文主要是分析Retrofit是如何将你编写的抽象方法一步步的变成一个网络请求,最终发起了这个网络请求,如果有什么地方存在问题,欢迎大家指出。
本文分析的思路如下
- retrofit是如何使用的
- retrofit是如何创建出接口类的对象
- retrofit调用抽象方法的时候发生了什么
- ServiceMethod做了什么
- CallAdapter的作用
- retrofit默认的CallAdapter做了什么
- retrofit在什么时候才会组装OKHttp网络请求
- 总结
Retrofit的使用
-
创建一个接口用于管理网络请求
如图所示,创建了一个接口ApiService,并写了一个GET请求的抽象方法loadInfo(),对于返回值的类型先不用较真,我们本文不会重点分析Convert的工作内容(当然大部分原因是因为我也没仔细的研究过)
public interface WanAndroidApi { @GET("tree/json") Call<TreeModel> getTreeData(); } -
创建Retrofit对象
不做过多的描述了,优秀的程序猿&程序媛都是了解创建的过程,不是本文的重点内容哈(甚至我都不想放代码块) 但是这里需要注意下两个参数 一个是CallAdapterFactory一个是ConverterFactory
private static Retrofit getRetrofit() { if (mRetrofit != null) return mRetrofit; OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); mRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(new Gson())) .build(); return mRetrofit; } -
通过Retrofit对象的create()方法创建接口的代理对象(直接看图,详细的内容后面会狠狠的分析)
public static WanAndroidApi getApiService() { return getRetrofit().create(WanAndroidApi.class); } -
调用代理对象抽象方法并调用 enqueue() execute()方法去执行网络请求(这里以异步enqueue()为例)
HttpUtil.getApiService().getTreeData() .enqueue(new Callback<TreeModel>() { @Override public void onResponse(Call<TreeModel> call, Response<TreeModel> response) { } @Override public void onFailure(Call<TreeModel> call, Throwable t) { } });
Retrofit的create()是如何创建出接口类对象的
查看Retrofit对象的create()方法发现了一行巨长的代码,是的,没有看错,是一行巨长的代码(哈哈哈嗝~)
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, @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);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
看到上面的代码,需要关注什么呢,难道要一行行的看下去嘛,当然不是,我们关注的是他是如何创建出我们接口类的对象出来的,熟悉Proxy.newProxyInstance()的程序员(应该加鸡腿的顶尖程序员)已经明白了,他是通过动态代理的方式创建出接口的实现类对象,建议不熟悉的同学可以去网上搜一下相关的知识点
Retrofit调用抽象方法的时候发生了什么
同样的,熟悉动态代理的同学都了解,当我们使用动态代理去调用接口的抽象方法的时候,会回调给我们InvocationHandler的 invoke()方法,并返回该方法的返回值
截取该部分的代码片段,然后重点关注最后的三行代码
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public 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);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
}
上面代码的核心就在这三句代码中,里面设计了ServiceMethod对象,OKHttpCall对象以及一个CallAdapter对象
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
一行行的分析每一行代码都在做些什么
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
通过loadServiceMethod(method)方法获取一个ServiceMethod对象,发现内部使用了缓存机制(缓存这个部分比较简单就不详细分析了,主要还是看这里面的创建流程)
贴一下loadServiceMethod()的代码,发现里面就是通过一个建造者设计模式来创建了一个ServiceMethod对象,并传入了retrofit和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 = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
查看具体的创建流程,就是对这个ServiceMethod的赋值
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
build()方法中的要素过多,这里省略了大部分的代码(对于callAdapter的选择,convert的选择我们放到使用的时候再讲)
public ServiceMethod build() {
// 给成员变量callAdapter赋值
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
// 给成员变量responseConverter赋值
responseConverter = createResponseConverter();
// 解析注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
// 返回一个ServiceMethod对象
return new ServiceMethod<>(this);
}
创建完ServiceMethod对象后,构建了一个OKHttpCall对象,将刚才创建的serviceMethod和抽象方法的具体参数args保存起来了(这个OKHttpCall当然不止是保存这么简单了,后面组建OKHttp的网络请求也是在这个类里面,等分析enqueue()方法的时候会分析)
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
最后调用了serviceMethod对象里面的callAdapter成员变量,并调用了其adapt()方法 将抽象方法的返回值返回出去
return serviceMethod.callAdapter.adapt(okHttpCall);
首先分析callAdapter是如何赋值的,在创建ServiceMethod对象的时候,通过createAdapter()方法给callAdapter进行赋值
callAdapter = createCallAdapter();
查看其createAdapter()方法,发现其最终是调用retrofit的callAdapter()方法创建的
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
回到Retrofit的源码里面,查看其是如何对callAdapter进行赋值的(通过遍历retrofit的adapterFactories集合,如果能够通过Factory的get()方法找到adapter对象则赋值,否则就抛出异常了)
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
/**
* Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
* #callAdapterFactories() factories} except {@code skipPast}.
*
* @throws IllegalArgumentException if no call adapter available for {@code type}.
*/
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = adapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
分析一波,集合里面的Factory对象都在啥时候添加的,如果没有添加的话会有什么样的结果
- Retrofit暴露了方法去添加
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
- 在创建Retrofit对象的时候有默认实现
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
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);
}
那么上面的抽象方法里面返回的CallAdapter对象具体是哪一种,他的adapt()方法到底有什么作用呢
- 分析目前集合里面有那几种Factory
- 具体用的哪一种 我在构建Retrofit的时候添加了一个RxJava2CAllAdapterFactory,而Retrofit还为我们默认提供了一种ExecutorCallAdapterFactory,所以当前集合里面应该是两个,那么两个Factory如何选择呢,这就要查看其get()方法的实现了
RxJava2CAllAdapterFactory的实现:
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
if (rawType != Observable.class && !isFlowable && !isSingle && !isMaybe) {
return null;
}
boolean isResult = false;
boolean isBody = false;
Type responseType;
if (!(returnType instanceof ParameterizedType)) {
String name = isFlowable ? "Flowable"
: isSingle ? "Single"
: isMaybe ? "Maybe" : "Observable";
throw new IllegalStateException(name + " return type must be parameterized"
+ " as " + name + "<Foo> or " + name + "<? extends Foo>");
}
Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType);
Class<?> rawObservableType = getRawType(observableType);
if (rawObservableType == Response.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Response must be parameterized"
+ " as Response<Foo> or Response<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
} else if (rawObservableType == Result.class) {
if (!(observableType instanceof ParameterizedType)) {
throw new IllegalStateException("Result must be parameterized"
+ " as Result<Foo> or Result<? extends Foo>");
}
responseType = getParameterUpperBound(0, (ParameterizedType) observableType);
isResult = true;
} else {
responseType = observableType;
isBody = true;
}
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
ExecutorCallAdapterFactory的实现:
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
从我上面举的例子可以发现,我们使用的Call类型的返回值,所以使用的也是Retrofit默认提供的ExecutorCallAdapterFactory
调用其CallAdapter的adapt()方法是将OKHttpCall包装在了ExecutorCallbackCall对象
至此,Retrofit从抽象方法变成一个Call类型的ExecutorCallbackCall对象的过程就简单的阐述完了,那么Retrofit是什么时候才会发送真正的网络请求呢,里面的线程切换又是如何做到的呢?
Retrofit在什么时候才会组装OKHttp网络请求
先说结论: 当调用enqueue() execute()方法的时候,才会真正的将网络请求发送出去
下面以异步执行的方式,查看是如何组装网络请求并进行回调的线程切换
HttpUtil.getApiService().getTreeData()
.enqueue(new Callback<TreeModel>() {
@Override
public void onResponse(Call<TreeModel> call, Response<TreeModel> response) {
}
@Override
public void onFailure(Call<TreeModel> call, Throwable t) {
}
});
通过之前一步步的分析,上面代码里面 getTreeData()返回的是一个ExecutorCallbackCall对象,并调用了enqueue()方法去发起网络请求,查看其enqueue()方法
@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) {
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);
}
});
}
});
}
发现执行的delegate成员变量的enqueue()方法,这个delegate对象是什么时候复制的呢,他的真实类型是什么呢? 在我们创建这个对象的时候会对其赋值,而我们传入的Call对象正是之前的OKHttpCall对象
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
那么代码回到OKHttpCall的enqueue()方法
是不是发现了熟悉的OKHttp包里面的call,并执行了call的enqueue()方法发起了OKHttp的网络请求,并将其结果回调给外界
public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
了解下这个OKHttp里面的call对象的生成
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
第一行代码非常重要,他就是将具体的参数填充到网络请求上去
Request toRequest(@Nullable Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
然后就是常规的通过OkHttpClient的newCall()方法创建Call对象
至此,一个网络请求已经发送出去了,那么最后一个问题就是默认的CallAdapter是如何解决线程调度的问题
在ExecutorCallAdapterFactory的enqueue()方法中对OKHttp的Call对象发起网络请求的回调函数里面通过callbackExecutor做一个线程调度,将其从子线程切换到主线程,那么这个成员变量是什么时候赋值的呢,他的execute()方法是如何线程切换的(其实可以不妨大胆的猜测一下Android里面线程切换的调度肯定是Handler,当然我是知道结果 Handler了,手动狗头~)
从构造函数中对其进行复制
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
在ExecutorCallAdapterFactory里面对ExecutorCallbackCall创建,
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
发现其也是一个成员变量从外界来的
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
再反推的话,有两个地方创建的不太好推了,我们从创建这个ExecutorCallAdapterFactory对象来分析具体的callbackExecutor是什么
记得我们构建Retrofit的时候,也是通过构建者最后的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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
emmmmm~~~~继续我们的反推,有两个地方调用了创建ExecutorCallAdapterFactory的地方
一个是Platform类里面
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
一个是Platform类的子类Android类里面
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
但是发现其还是从外界传入的callbackExecutor(疯了都)
但是,走到这一步就快了,因为你发现,这两个方法都在构建Retrofit类的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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
那么现在的问题是,这个platform对象的具体类型,他的defaultCallbackExecutor()返回的到底是什么?
platform对象是Retrofit的成员变量,通过两种方式赋值
通过构造函数赋值,但是明显我并没有调用过这个函数
Builder(Platform platform) {
this.platform = platform;
// 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());
}
排除法,就剩一种赋值方式了
public Builder() {
this(Platform.get());
}
查看这个get()方法 到底返回了什么
static Platform get() {
return PLATFORM;
}
private static final Platform PLATFORM = findPlatform();
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
最终,最后的最后发现我们创建的Android!!!!,callbackExecutor的赋值肯定也是Android做的了,返回的是MainThreadExecutor()
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
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);
}
}
}
那么,我们再次的回到ExecutorCallbackCall的enqueue()方法里面,做线程切换的是MainThreadExecutor的execute()方法,他是Handler发送了一个Runnable()的任务,这个任务最终会切换到主线程中(什么?不知道为啥Handler post(Runnable)会在主线程执行Runnable的run()方法,下一篇我们就分析这个过程,整个过程也是比较简单的)!!
至此,线程切换的内容也阐述完了
总结
这篇文章是自己写的第一篇技术类型博客,可能分析的不到位,只是大概的分析了一下Retrofit是如何将一个抽象方法变成一个Call类型的,接着分析如何发起一个网络请求,最后分析了默认的情况下是如何进行回调的线程切换,如有分析不对的情况,欢迎指出