前言
每次看完Retrofit的源码,下次再看时很容易就忘记了,Retrofit的源码中用了大量的设计模式,刚开始看时感觉就是代码中调来调去。。。绕来绕去。。。真的。。。没有点到即止的话~很容易就晕了,所以这次我从使用的API的角度出发,将对Retrofit的解析写成笔记.
Retrofit源码基于版本2.4.0
首先看下Retrofit的基本使用:
-
1.首先创建用于网络请求的API接口:
public interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> contributors( @Path("owner") String owner, @Path("repo") String repo); }
-
2.创建用于接收响应实体的类
public static class Contributor { public final String login; public final int contributions; public Contributor(String login, int contributions) { this.login = login; this.contributions = contributions; } }
-
3.创建Retrofit实例并发起请求
public static void main(String... args) throws IOException { Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); GitHub github = retrofit.create(GitHub.class); Call<List<Contributor>> call = github.contributors("square", "retrofit"); //同步请求 List<Contributor> contributors = call.execute().body(); //异步请求 call.enqueue(new Callback<List<Contributor>>() { @Override public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) { } @Override public void onFailure(Call<List<Contributor>> call, Throwable t) { } });
2.从Retrofit的基本API入手:
a.Retrofit构建过程
-
1.Retrofit.Builder(): 获取对应平台的Platform实例,这里是获取到Android类的实例.
public final class Retrofit { public static final class Builder { Builder(Platform platform) { this.platform = platform; } public Builder() { //Platform是获取相应的平台,有Android、Java等 this(Platform.get()); } } }
在Android类里主要是维护了MainThreadExecutor类,来将子线程切换到主线程
//适配平台 class Platform { private static final Platform PLATFORM = findPlatform(); static Platform get() { return PLATFORM; } //寻找对应的平台 private static Platform findPlatform() { try { //通过JVM加载类的方式判断是否是Android平台 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平台对应的类 static class Android extends Platform { //返回可以将子线程切换到主线程的线程池 @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } //工厂方法模式,将Executor实例装载进工厂类 @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { //Android主线程的Hnadler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { //将子线程切换到主线程 handler.post(r); } } }
-
2.baseUrl( ): 判断基础的url不能为空,将String类型的url转化成HttpUrl实例
public final class Retrofit { public static final class Builder { public Builder baseUrl(String baseUrl) { //基础的url不能为空 checkNotNull(baseUrl, "baseUrl == null"); //将String类型的url 转化成 HttpUrl实例 HttpUrl httpUrl = HttpUrl.parse(baseUrl); if (httpUrl == null) { throw new IllegalArgumentException("Illegal URL: " + baseUrl); } return baseUrl(httpUrl); } } }
HttpUrl类用了Build模式来创建
public final class HttpUrl { public static final class Builder { @Nullable public static HttpUrl parse(String url) { //build模式创建HttpUrl HttpUrl.Builder builder = new HttpUrl.Builder(); HttpUrl.Builder.ParseResult result = builder.parse((HttpUrl)null, url); return result == HttpUrl.Builder.ParseResult.SUCCESS ? builder.build() : null; } } }
-
3.addConverterFactory(): 将数据转换器工厂添加到converterFactories这个存放数据转换器工厂(集合的元素类型为Converter.Factory)的集合中
//将数据转换器工厂添加到converterFactories这个存放数据转换器工厂(集合的元素类型为Converter.Factory)的集合中 // 比如 GsonConverterFactory这个Gson数据转换器 public Builder addConverterFactory(Converter.Factory factory) { converterFactories.add(checkNotNull(factory, "factory == null")); return this; }
-
4.addCallAdapterFactory(): 将网络请求适配器工厂添加到callAdapterFactories这个存放网络请求适配器工厂(集合的元素类型为CallAdapter.Factory)的集合中
//将网络请求适配器工厂添加到callAdapterFactories这个存放网络请求适配器工厂(集合的元素类型为CallAdapter.Factory)的集合中 //比如 开发者可添加 RxJavaCallAdapterFactory 这个RX网络请求适配器 public Builder addCallAdapterFactory(CallAdapter.Factory factory) { callAdapterFactories.add(checkNotNull(factory, "factory == null")); return this; }
-
5.build():
-
检查了OkHttpClient和回调线程池类Executor是否传入值,未传入则创建默认的值,已传入则使用开发者设置的值
-
往存放数据转换器工厂的集合存入开发者设置的数据转换器工厂(例如GsonConverterFactory)和系统默认的数据转换器工厂(BuiltInConverters)
-
往存放网络请求适配器工厂的集合存入开发者设置的网络请求适配器工厂(例如RxJavaCallAdapterFactory)和系统默认的网络请求适配器工厂(ExecutorCallAdapterFactory)
- ExecutorCallAdapterFactory里存了MainThreadExecutor实例
-
返回Retrofit实例
public Retrofit build() { //必须调用 baseUrl() 这个函数传入基本的url,这里才不会抛异常 if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } //开发者是否传入OkHttpClient实例,未传入则创建 okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } //开发者是否传入 用于回调的线程池类,未传入则获取对应平台(这里是Android类)的回调线程池实例 Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { //这里的Platform = Android //platform.defaultCallbackExecutor()获取的是MainThreadExecutor实例 callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); //将MainThreadExecutor装载进ExecutorCallAdapterFactory工厂实例里,并将工厂实例添加进 网络请求适配器的集合里 callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size()); // 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); //Collections.unmodifiableList()函数是将集合转化成只读的 return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); }
-
b. 创建请求接口的实例
-
1.retrofit.create(): 使用动态代理模式对网络请求接口类进行代理,返回代理接口的实例,这里invoke函数的代码在下面调用网络请求接口的函数时会被执行,重点在下面
public <T> T create(final Class<T> service) { //检查网络请求接口类是不是接口,有没继承其他接口 等 Utils.validateServiceInterface(service); //判断是否需要提前缓存ServiceMethod对象, validateEagerly默认为false if (validateEagerly) { eagerlyValidateMethods(service); } // 使用动态代理模式拿到 网络请求接口类的函数的注解、函数参数、函数返回值等相关信息 // 返回"接口调用实例Call",其实这个Call是ExecutorCallbackCall类(Retrofit的Call的实现类)的实例,这里只要先记得返回值是ExecutorCallbackCall类的实例即可 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); } //注释1:ServiceMethod接口负责存 网络请求接口类的函数的注解、函数参数、函数返回值等相关信息 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); //注释2:OkHttpCall是对Retrofit.Call的实现,实际该类主要用到OkHttp.Call(rawCall这个变量) 来进行enqueue、execute请求 OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); //注释3:这里实际上返回的是ExecutorCallbackCall类(Retrofit的Call的实现类)的实例 return serviceMethod.adapt(okHttpCall); } }); }
c. 调用网络请求接口的函数
-
1.github.contributors(): 这里会回调到上一步返回的代理接口中的InvocationHandler中的invoke函数
-
在invoke函数里拿到网络请求接口类的函数的注解、函数参数、函数返回值等相关信息,存入ServiceMethod里
-
给ServiceMethod设置合适的数据转换器和网络请求适配器
-
创建OkHttpCall,OkHttpCall是对Retrofit.Call的实现,实际该类主要用到OkHttp.Call(rawCall这个变量) 来进行enqueue、execute请求
-
最后返回 ExecutorCallbackCall类(Retrofit的Call的实现类)的实例
在上面的invoke函数中,最重要的是标有 “注释1”、“注释2” 和 “注释3” 这3行代码,先看注释1的代码
//注释1:ServiceMethod接口负责存 网络请求接口类的函数的注解、函数参数、函数返回值等相关信息 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); public final class Retrofit { /** * 该函数主要加载网络请求接口类的函数的注解、函数参数、函数返回值等相关信息 * 先从缓存中查找是否有该method对应的ServiceMethod实例,有则返回,没有则创建之后返回 */ ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { //解析注解配置得到了ServiceMethod,ServiceMethod同样是Build模式创建 result = new ServiceMethod.Builder<>(this, method).build(); //存进缓存里 serviceMethodCache.put(method, result); } } return result; } }
上面的ServiceMethod是通过Build模式创建的
final class ServiceMethod<R, T> { static final class Builder<T, R> { Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; //获取网络请求接口里函数的注解 this.methodAnnotations = method.getAnnotations(); //获取网络请求接口里函数的参数类型 this.parameterTypes = method.getGenericParameterTypes(); //获取网络请求接口里函数的参数注解 this.parameterAnnotationsArray = method.getParameterAnnotations(); } public ServiceMethod build() { //createCallAdapter函数是从callAdapterFactories集合里找到合适的网络请求适配器 callAdapter = createCallAdapter(); //获取网络请求接口类的函数的返回值 responseType = callAdapter.responseType(); if (responseType == Response.class || responseType == okhttp3.Response.class) { throw methodError("'" + Utils.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } //createResponseConverter函数是从converterFactories集合里找到合适的数据转换器 responseConverter = createResponseConverter(); for (Annotation annotation : methodAnnotations) { parseMethodAnnotation(annotation); } ...省略部分代码 } } }
上面build函数中调用createCallAdapter函数生成callAdapter,调用createResponseConverter函数生成responseConverter,这两个函数留到下一篇Retrofit源码解析(二)再去剖开,有时就应该点到即止,不然太多的细节绕着绕着就晕了,先记住这两个函数是获取了网络请求适配器和数据转换器,
根据上面的请求函数的返回值Call<List< Contributor >>,这里获取到的网络请求适配器是ExecutorCallAdapterFactory(封装MainThreadExecutor的工厂类),获取到的数据转换器是开发者通过api设置的GsonConverterFactory
.addConverterFactory(GsonConverterFactory.create())
接着回到注释2的代码,可以看到主要创建了OkHttpCall,而OkHttpCall是实现了Retrofit.Call接口, 实际上该类主要用到OkHttp.Call(rawCall这个变量) 来发起enqueue(异步)或execute(同步)请求,所以OkHttpCall是封装了OkHttp框架的enqueue(异步)和execute(同步)请求
final class OkHttpCall<T> implements Call<T> { //...省略部分代码 private @Nullable okhttp3.Call rawCall; //异步请求 @Override public void enqueue(final Callback<T> callback) { checkNotNull(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 { //createRawCall() 返回的是 OkHttp.RealCall类的实例 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) { callFailure(e); return; } try { //将响应结果回调返回 callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } @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) { t.printStackTrace(); } } }); } //同步请求 @Override public Response<T> execute() throws IOException { okhttp3.Call call; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; if (creationFailure != null) { if (creationFailure instanceof IOException) { throw (IOException) creationFailure; } else if (creationFailure instanceof RuntimeException) { throw (RuntimeException) creationFailure; } else { throw (Error) creationFailure; } } call = rawCall; if (call == null) { try { //createRawCall() 返回的是 OkHttp.RealCall类的实例 call = rawCall = createRawCall(); } catch (IOException | RuntimeException | Error e) { throwIfFatal(e); // Do not assign a fatal error to creationFailure. creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } //解析服务端的响应数据 return parseResponse(call.execute()); } private okhttp3.Call createRawCall() throws IOException { //serviceMethod.toCall 返回的是 OkHttp.RealCall类的实例 // 所以这里的call可以直接发起同步或异步请求 okhttp3.Call call = serviceMethod.toCall(args); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; } }
上面的代码看起来还是很顺的,但还是忍不住扔出几个疑问,
- createRawCall函数中的call=OkHttp.RealCall类是如何创建的?
- 还有enqueue函数和execute函数中调用的parseResponse(rawResponse)函数,是怎么解析响应数据的?
这两个问题留到下一篇Retrofit源码解析(二)再去剖开,先记住createRawCall函数中生成的是OkHttp.RealCall类的实例即可
接着来到注释3的代码,调用了serviceMethod.adapt(okHttpCall),跟进去ServiceMethod类的adapt函数,发现调用到了CallAdapter接口的adapt函数,这里就得去找CallAdapter接口的实现类, 才能知道adapter函数返回的具体实现类是什么,这个问题留到下一篇Retrofit源码解析(二)再去剖开,先记住这里是返回了ExecutorCallbackCall类的实例
d. call发起异步请求
-
1.call.enqueue(): 此处的call = ExecutorCallbackCall类,这里要结合上面的OkHttpCall类,来理清异步请求从Retrofit框架递交到OkHttp框架的流程
-
在ExecutorCallbackCall类里,通过OkHttpCall类发起异步请求,其中OkHttpCall类的createRawCall函数返回的是OkHttp.RealCall类的实例, 所以这里实际上是RealCall.enqueue(),也就是将异步请求交给OkHttp框架去发起;
-
在OkHttpCall类中解析服务端返回的响应数据,转换为网络请求函数中定义的返回类型,其中涉及到的数据转换器类是BuiltInConverters 或 GsonResponseBodyConverter
-
通过MainThreadExecutor将子线程回调到主线程,在主线程中将响应结果回调返回
final class ExecutorCallAdapterFactory extends CallAdapter.Factory { static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; //这里传入的delegate = OkHttpCall实例,callbackExecutor = MainThreadExecutor实例 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 = OkHttpCall实例 //OkHttpCall是对Retrofit.Call的实现,实际该类主要用到OkHttp.Call(rawCall这个变量) 来进行enqueue、execute请求 delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { //callbackExecutor = MainThreadExecutor, 主要从子线程切换到主线程并返回响应结果 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 Response<T> execute() throws IOException { //这里的delegate = OkHttpCall实例 return delegate.execute(); } } }
3.总结
a. Retrofit构建过程
- 1.Retrofit.Builder(): 获取对应平台的Platform实例,这里是获取到Android类的实例. 在Android类里提供生成网络请求适配器MainThreadExecutor的函数
- 2.baseUrl(): 判断基础的url不能为空,将String类型的url 转化成 HttpUrl实例, HttpUrl类用了Build模式来创建
- 3.addConverterFactory(): 将数据转换器添加到converterFactories这个存放数据转换器(集合的元素类型为Converter.Factory)的集合中
- 4.addCallAdapterFactory(): 将网络请求适配器添加到callAdapterFactories这个存放网络请求适配器(集合的元素类型为CallAdapter.Factory)的集合中
- 5.build():
- 检查了OkHttpClient和回调线程池类Executor是否传入值,未传入则创建默认的值,已传入则使用开发者设置的值
- 往存放数据转换器的集合 存入 开发者设置的数据转换器(例如GsonConverterFactory) 和 系统默认的数据转换器(BuiltInConverters)
- 往存放网络请求适配器的集合 存入 开发者设置的网络请求适配器(例如RxJavaCallAdapterFactory) 和系统默认的网络请求适配器(ExecutorCallAdapterFactory)
- ExecutorCallAdapterFactory里 存了 MainThreadExecutor实例
- 返回Retrofit实例
b. 创建请求接口的实例
-
1.retrofit.create():
- 使用动态代理模式对网络请求接口类进行代理,返回代理接口的实例
c. 调用网络请求接口的函数
-
1.github.contributors(): 这里会回调到上一步返回的代理接口中的 InvocationHandler中的invoke函数
- 在invoke函数里拿到网络请求接口类的函数的注解、函数参数、函数返回值等相关信息,存入ServiceMethod里
- 给ServiceMethod设置合适的数据转换器和网络请求适配器
- 创建OkHttpCall,OkHttpCall是对Retrofit.Call的实现,实际该类主要用到OkHttp.Call(rawCall这个变量) 来进行enqueue、execute请求
- 最后返回 ExecutorCallbackCall类(Retrofit的Call的实现类)的实例
d. call发起异步请求
-
1.call.enqueue(): 这里的call = ExecutorCallbackCall类
- 通过OkHttpCall类发起异步请求,其中OkHttpCall类的createRawCall函数返回的是OkHttp.RealCall类的实例, 所以这里是RealCall.enqueue()
- 解析服务端返回的响应数据,转换为网络请求函数中定义的返回类型,其中涉及到的数据转换器类是BuiltInConverters 或 GsonResponseBodyConverter
- 通过MainThreadExecutor将子线程回调到主线程,在主线程中将响应结果回调返回
4. 补充
Retrofit的Converter类可以使得请求函数的入参和返回类型丰富起来,比如请求函数的参数中有文件类型的,我们可以通过定制Converter类,使得入参时可直接传File类型之类的元素. 同样也可以根据返回类型,定制类似GsonResponseBodyConverter这样的数据转化器,具体的参考 深入浅出 Retrofit,这么牛逼的框架你们还不来看看?
本篇的几个疑问点请参考 Retrofit源码解析(二)