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()
时,实际上调用的是这个包装类
里面的ExecutorCallbackCall
enqueue()
,然后该方法内部又调用了间接发起网络请求的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