retrofit和okhttp都是用来做网络请求的,并且都是出自Square公司。其中okhttp是用来代替android原生的HttpClient和HttpURLConnection的,官方也是建议用okhttp作为android底层的网络通信库。而retrofit将okhttp进一步封装,让开发者更方便的做网络请求。
通过本章的学习我们能够了解并掌握:
- retrofit整体框架
- retrofit是如何封装okhttp来做请求的?
- retrofit如何做数据解析的?
retrofit整体框架
先根据官网的教程,写一个简单的例子:
//1.申明接口
interface GitHubService {
@GET("users/{user}/repos")
fun listRepos(@Path("user") user: String?): Call<List<Repo>>
fun listRepos2(@Path("user") user: String?): Single<List<Repo>>
}
//2.创建retrofit
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.baseUrl("https://api.github.com/")
.build()
//3.实现接口
val service = retrofit.create(GitHubService::class.java)
//4.调用接口
val repos: Call<List<Repo>> = service.listRepos("longdw")
//5.发起请求
repos.enqueue(object: Callback<List<Repo>> {
override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) {
println("response-->${response.body()!![0].name}")
}
override fun onFailure(call: Call<List<Repo>>, t: Throwable) {
}
})
只需要简单的5个步骤,就能够实现请求网络并将服务器返回的数据解析成对象,并且能直接在onResponse()和onFailure()回调方法里面直接操作UI。
是不是简单方便又高效,接下来开始深入源码内部。当我尝试进入enqueue()方法或者listRepos()方法查看具体调用过程时,发现都是接口,找不到具体的实现类,也就是说第4、5步走不下去了,这可咋办呢?那就从第3步开始看,从retrofit.create()寻找突破口:
public final class Retrofit {
...
public <T> T create(final Class<T> service) {
validateServiceInterface(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);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
...
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;
}
}
上面选取部分Retrofit源码,其中create()方法是Retrofit的核心,该方法有两个关键点:
(1)validateServiceInterface(service)
该方法我没贴出来,主要作用是验证我们写的接口有没有问题,比如接口不能有泛型。大家看源码后会发现该方法里面有个validateEagerly关键字,默认是false,如果设置为true的话,会在接口中的方法还没调用的时候,也就是只在我们调用retrofit.create()的时候就开始检查所有方法是否合法了。所以我们在生产环境不要开启这个,否则可能会导致应用启动速度慢,如果接口中有很多方法,还有可能会导致ANR等问题。
(2)Proxy.newProxyInstance()
这个就是我们常看到或者听到的动态代理,有3个参数:ClassLoader、Class数组、InvocationHandler匿名类。其中就Retrofit来讲,第二个参数传的是GitHubService,其基本原理就是当我们调用此接口中的方法时,比如上例中的listRepos()方法,动态代理会最终调用InvocationHandler匿名类中的invoke(Object proxy, Method method, @Nullable Object[] args)方法。用伪代码表示就是长下面这样:
public class GitHubServiceImpl implements GitHubService {
InvocationHandler invocationHandler = 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);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
};
@NonNull
@Override
public Call<List<Repo>> listRepos(@Nullable String user) {
Method method = GitHubService.class.getMethod("listRepos", String.class);
return invocationHandler.invoke(this, method, user);
}
}
通过上面的介绍,我们了解到Retrofit的核心实际上就是运用了动态代理作为桥梁,当我们调用接口方法时,动态代理会自动创建一个类作为代理类,用代理类来包装我们的请求。
retrofit是如何封装okhttp来做请求的?
本小结重点来讲解下代理类中都干了些啥。
以InvocationHandler.invoke()作为切入点,首先判断如果调用的方法是Object中的方法,比如toString()、hashCode()等,就直接调用,否则调用loadServiceMethod(method).invoke(args)。
loadServiceMethod(method)里面,通过ServiceMethod.parseAnnotations()解析出接口方法的注解、传入的参数、返回的参数等信息,最终以HttpServiceMethod类型返回,并用serviceMethodCache缓存起来。通过调用HttpServiceMethod的invoke()方法来包装请求的过程以及数据解析的过程。
接下来以loadServiceMethod(method).invoke(args)的invoke()方法作为切入点,先看ServiceMethod类。
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类。
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
...
Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
if (!isKotlinSuspendFunction) {
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else ...
}
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter(
Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
}
HttpServiceMethod(
RequestFactory requestFactory,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
@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);
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);
}
}
}
以上是HttpServiceMethod的核心代码,loadServiceMethod(method).invoke(args)最终调用的是HttpServiceMethod的invoke()方法,主要做了两件事:
(1)创建OkHttpCall对象
final class OkHttpCall<T> implements Call<T> {
OkHttpCall(
RequestFactory requestFactory,
Object[] args,
okhttp3.Call.Factory callFactory,
Converter<ResponseBody, T> responseConverter) {
this.requestFactory = requestFactory;
this.args = args;
this.callFactory = callFactory;
this.responseConverter = responseConverter;
}
private okhttp3.Call getRawCall() {
okhttp3.Call call = rawCall;
return rawCall = createRawCall();
}
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
return call;
}
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
call = rawCall = createRawCall();
if (failure != null) {
callback.onFailure(this, failure);
return;
}
call.enqueue(
new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
response = parseResponse(rawResponse);
callback.onResponse(OkHttpCall.this, response);
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
callback.onFailure(OkHttpCall.this, e);
}
});
}
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
T body = responseConverter.convert(catchingBody);
return Response.success(body, rawResponse);
}
}
OkHttpCall类里面同样也有几个需要关注的重点
a)enqueue()方法,Call通过此方法来发起调用。
b)通过callFactory.newCall()来创建真正的发起网络请求的Call。
c)通过responseConverter.convert()来解析服务器返回的数据。
这几个方法等会再详细介绍,先继续往下看。
(2)调用adapt()方法
实际上调用的是CallAdapted.adapt()方法,接着执行callAdapter.adapt(call)。看上面HttpServiceMethod源码我们得知,callAdapter实际上是retrofit.callAdapter()创建的。接着我们再看Retrofit源码:
public final class Retrofit {
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;
}
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
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;
}
}
}
public static final class Builder {
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> 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);
}
}
}
看到这里我们得停下来,思考下我们的初衷是什么,我们的目的是要找到callAdapter是如何创建的,进而找到adapt()方法的逻辑。
仔细阅读上面的源码会发现,callAdapter是由Builder的build()方法创建的callAdapterFactories创建的。callAdapterFactories是个集合,默认的callAdapter是由platform.defaultCallAdapterFactories(callbackExecutor)创建。callbackExecutor参数是一个Executor:
static final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
defaultCallAdapterFactories()返回的是DefaultCallAdapterFactory:
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) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = 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);
}
};
}
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) {
Objects.requireNonNull(callback, "callback == null");
delegate.enqueue(
new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(
() -> {
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(() -> callback.onFailure(ExecutorCallbackCall.this, t));
}
});
}
@Override
public boolean isExecuted() {
return delegate.isExecuted();
}
@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}
}
}
看到这里大家应该长叹一口气,我们要的CallAdapter终于找到了——就是DefaultCallAdapterFactory.get()返回的对象。还记得上面callAdapter.adapt(call)吗?我们当初就是从这里一步步往下深入源码的。
接着再看adapt(call),返回的是ExecutorCallbackCall。原来饶了这么一圈,又给我包装了一个ExecutorCallbackCall。回到开头的例子中,当我们调用call.enqueue()时,实际上调用的是这个包装类里面的ExecutorCallbackCallenqueue(),然后该方法内部又调用了间接发起网络请求的OkHttpCall类中的enqueue(),最后在OkHttpCall类的enqueue()方法内部调用直接发起网络请求的okhttp3.Call类的enqueue()。

有人会疑惑,为啥一个调用要包装两层呢?
首先说下ExecutorCallbackCall,这个类大家注意看下onResponse()和onFailure()这两个回调,不是直接调用callback.xxx(),而是包装了一层callbackExecutor.execute(),这个callbackExecutor就是我们上面贴出来的MainThreadExecutor,是不是瞬间明白了?没错,就是将回调信息通过主线程返回。
再说下OkHttpCall,用这个类又包装了下,它的作用是方便在内部处理返回的信息,比如调用我们传入的responseConveter来解析数据。
看到这里,相信大家对Retrofit整体的流程应该有了一个清晰的认识了,最后我们再看看前面留下的两个没有深入讲解的知识点:
1)通过callFactory.newCall()创建okhttp3.Call。2)通过responseConverter.convert()来解析数据。
retrofit如何做数据解析的?
首先讲下callFactory.newCall()是怎么创建okhttp3.Call的。
callFactory其实跟callAdapter的套路差不多,结合HttpServiceMethod和Retrofit源码,找到Builder类build()方法中的callFactory,实际上就是OkHttpClient()。
最后再讲下responseConverter.convert()是怎么解析数据的。
同样的套路,找到Builder类build()中的converterFactories集合。还记得我们初始化Retrofit传入的addConverterFactory(GsonConverterFactory.create())吗?没错,最终是通过GsonConverterFactory来解析数据的。
至此,整个Retrofit的原理,包括调用过程以及数据的解析过程都讲解完毕了,当然细节部分比如怎么解析注解和参数等,这些对照源码看下应该都能明白。本篇文章主要还是讲解整个大的框架,先从宏观上把握了整个流程,再去深入源码,就能够掌握更多的细节。不能一开始就抠细节,这样到最后自己都搞晕了,就更没信心继续往下看了。
转载请注明出处——https://www.longdw.com