Retrofit源码导读
16lz
2021-01-24
一、Retrofit简介 Retrofit是由 Square公司 出品的针对于Android和Java的类型安全的Http客户端,网络服务基于 OkHttp 。 二、代码阅读前基础知识准备 在阅读Retrofit源代码前需要了解以下方面的基础知识点。 2.1 android耗时操作的处理套路 在Android进行耗时操作时,通常会将耗时任务放在子线程或线程池中执行,执行完毕后的结果再通过回调返回到主线程中,在回调过程中伴随有线程的切换。
Android中这种耗时操作的处理套路,可以参考在子线程中对UI界面中进行更新,一般使用Handler来进行回调和切换线程。 Retrofit在处理耗时的网络请求操作过程中也采用了这样的套路,只是Retrofit采用的套路比较深。Retrofit网络请求框架的基本流程如下,图下的Executor一般采用OKhttp库充当,在OKhttp模块内有线程池,可以不断接收网络请求线程。网络请求的执行结果被解析后返回,返回时一般使用Retrofit中的 defaultCallbackExecutor进行切换线程的操作。
2.2 设计模式 Retrofit在设计中采用的大量的设计模式,众多的设计模式造就了Retrofit的超级解耦和好用,下面对Retrofit采用的设计模式进行一个大致的列举和说明。 抽象工厂模式 抽象工厂模式属于创建者模型,主要是为了将用户从固定类型的创建过程中解耦出来,隐藏复杂的new操作。 Retrofit中采用的是抽象工厂模式,包括有 okhttp3.Call.Factory,CallAdapter.Factory 和 Converter.Factory。
Retorfit中默认有CallAdapter接口的实现,看Retrofit中的默认实现
但是一般情况下都是用现在RxJava,所以就有了RxJavaCallAdapterFactory供我们使用。
RxJavaCallAdapterFactory和DefaultCallAdapterFactory两个具体工厂类生产出来的产品就是SimpleCallAdapter和CallAdapter。 适配器模式 适配器模式将一个类的接口,转化成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间。 CallAdapter的作用是调度网络请求,在里面的adapt方法用了适配器模式,将默认的Call适配到客户端想要用的Adapter上。 外观模式(门面模式) 外观模式(门面模式)属于结构性模式,它隐藏了系统的复杂性,为子系统的一组接口提供一个统一的访问接口,这个接口使得子系统更容易被访问或使用。 Retrofit的门面就是 retrofit.create() 另外Retrofit模式还包括享元模式,装饰者模式,建造者模式,动态代理模式和策略模式等等。 三、Retrofit源码分析 一个Retrofit实例
3.1 源码解析之Retrofit对象的创建
Retrofit中的创建代码
Retrofit代码的创建与两个主要任务:
线程切换的过程
3.2 创建接口实现类 Retrofit.create(Api.class) 创建并返回一个会拦截接口方法的动态代理对象实例,接口方法被调用时,会被其拦截,内部将接口方法适配成HTTP Call,再构造对应的OKHttpCall,这里的OKHttpCall是OKHttp的一个包装类,用它生成OkHttp。最后通过CallAdapter.adapt()转换成Retrofit适用的call delegares(即 ExecutorCallbackCall)。
上述 ServiceMethod 内部主要是将方法中的注解取出,转换成HTTP Call的逻辑,暂且不深究。 3.3 执行http请求 在示例代码中调用call.execute()就会执行http请求,这里的call是OKHttpCall的一个对象。从下面的代码可见,调用了OKHttpCall.execute(),该方法会生成一个okhttp3.Call将任务抛给OKHttp,完了调用parseResponse,用Converter将okhttp3.Response转换成我们在范型中指定的类型Response response = call.execute(),我指定了okhttp3.ResonseBody。然后返回结果。如果我在构造Retrofit时提供了GsonConverter,addConverterFactory(GsonConverterFactory.create())那么上面的T body = responseConverter.convert(catchingBody);responseConverter就是GsonConverter。
四、Retrofit流程总结 1. Retrofit对象的构建 Retrofit.Builder()...build():①构建OkHttpClient,目前Retrofit仅支持OkHttpClient;②构建Executor:优先根据用户提供的callBackExcecutor来构建,若用户没有提供,则提供defaultCallbackExecutor(其内部会获取MainLooper构建handler,execute方法直接handler.post(runnable),实现在主线程上的操作);③使用executor来构建adapterFactories集合,优先将用户提供的adapterFactory加入到其中,再加上defaultCallAdapterFactory(传入②创建的callbackExecutor,defaultCallAdapterFactory内部持有OkHttpCall,在其enqueue方法中的onResponse方法调用defaultCallbackExecutor.execute方法,从而实现线程切换操作);④最终使用Retrofit构造方法构建Retrofit实例对象 2. Retrofit接口方法的实现方式 retrofit.create(接口名.class):①create方法创建并返回动态代理对象实例,动态代理对象内部会拦截接口方法的调用②动态代理内部通过ServiceMethod将接口方法适配成HTTP Call,再构造对应的OkHttpCall,最后通过CallAdapter转换成Retrofit适用的call delegate(ExecutorCallbackCall)。 3. 使用动态代理(接口实现类)调用接口方法得到Call、使用call.enqueue进行异步请求:①调用接口方法时,动态代理对象(接口实现类)内部拦截;②调用call.enqueue,内部会调用ExecutorCallAdapter的enqueue方法,enqueue中onResponse方法调用defaultCallbackExecutor.execute方法,使用主线程Handler.post(runnable)从而实现线程切换操作。
Android中这种耗时操作的处理套路,可以参考在子线程中对UI界面中进行更新,一般使用Handler来进行回调和切换线程。 Retrofit在处理耗时的网络请求操作过程中也采用了这样的套路,只是Retrofit采用的套路比较深。Retrofit网络请求框架的基本流程如下,图下的Executor一般采用OKhttp库充当,在OKhttp模块内有线程池,可以不断接收网络请求线程。网络请求的执行结果被解析后返回,返回时一般使用Retrofit中的 defaultCallbackExecutor进行切换线程的操作。
2.2 设计模式 Retrofit在设计中采用的大量的设计模式,众多的设计模式造就了Retrofit的超级解耦和好用,下面对Retrofit采用的设计模式进行一个大致的列举和说明。 抽象工厂模式 抽象工厂模式属于创建者模型,主要是为了将用户从固定类型的创建过程中解耦出来,隐藏复杂的new操作。 Retrofit中采用的是抽象工厂模式,包括有 okhttp3.Call.Factory,CallAdapter.Factory 和 Converter.Factory。
public interface CallAdapter |
final class DefaultCallAdapterFactory extends CallAdapter.Factory { static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory(); @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 @Override public |
public final class RxJavaCallAdapterFactory extends CallAdapter.Factory { @Override public CallAdapter<?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { ...... } CallAdapter private CallAdapter |
public class LearnRetrofit { public static final String API_URL = "https://api.github.com"; //创建接口 public interface GitHub { @GET("/repos/{owner}/{repo}/contributors") Call public static void main(String[] args) throws IOException { //创建Retrofit对象 Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .build(); //动态生成一个代理对象 GitHub github = retrofit.create(GitHub.class); //生成一个OKHttpCall的代理对象 Call //返回结果 Response |
Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL) .build(); |
public Retrofit build() { ... // 创建OkHttp,目前Retrofit只支持OkHttp okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } // 创建Executor,见步骤3 Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. // 对adapters进行保护性拷贝,并且加入默认的call adapter(使用上面创建的Executor来构建,可以认为是把主线程中的Handler传入) // 构建adapterFactories集合,将defaultAdapterFactory加入其中,见步骤4 List // Make a defensive copy of the converters. // 对converters进行保护性拷贝 // 一般传入的为GsonConverterFactory对象,其作用主要是将json转换成java对象 List //最终完成Retrofit对象构建 return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); } |
- 创建callbackExecutor(内部获取主线程MainLooper来构建Hanlder,其execute方法本质是Handler.post(runnable),待用于线程切换)。
- 构建adapterFactories集合,将defaultAdapterFactory加入其中(ExecutorCallAdapterFactory类,线程切换关键实现,内部持有OkHttp代理delegate,在delegate.enqueue中的onRespond方法内使用刚刚创建的callbackExecutor.execute方法,从而实现线程切换)。
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { // 返回MainThreadExecutor return new Platform.Android.MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) { return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { // 从主线程得到MainLooper,构建Handler private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { // execute方法本质:通过handler,在主线程上执行该runnable handler.post(r); } } } |
@Override public void enqueue(final Callback @Override public void onFailure(final Call |
Api api = retrofit.create(Api.class); // create方法内部实现,返回一个动态代理实例 public |
final class OkHttpCall //核心方法 @Override public Response synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; if (creationFailure != null) { if (creationFailure instanceof IOException) { throw (IOException) creationFailure; } else { throw (RuntimeException) creationFailure; } } call = rawCall; if (call == null) { try { //将任务抛给OKHttp call = rawCall = createRawCall(); } catch (IOException | RuntimeException e) { creationFailure = e; throw e; } } } if (canceled) { call.cancel(); } //转换结果 return parseResponse(call.execute()); } //生成okhttp3.Call private okhttp3.Call createRawCall() throws IOException { //这个callFactory就是OKHttpClient okhttp3.Call call = callFactory.newCall(requestFactory.create(args)); if (call == null) { throw new NullPointerException("Call.Factory returned null."); } return call; } //将okhttp3.Response转换成Response Response // Remove the body's source (the only stateful object) so we can pass the response along. rawResponse = rawResponse.newBuilder() .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength())) .build(); int code = rawResponse.code(); if (code < 200 || code >= 300) { try { // Buffer the entire body to avoid future I/O. ResponseBody bufferedBody = Utils.buffer(rawBody); return Response.error(bufferedBody, rawResponse); } finally { rawBody.close(); } } if (code == 204 || code == 205) { return Response.success(null, rawResponse); } ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { //这个responseconverter就是默认提供的RequestBodyConverter,当然我们可以替换成自己的converter比如GsonConverter T body = responseConverter.convert(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { // If the underlying source threw an exception, propagate that rather than indicating it was // a runtime exception. catchingBody.throwIfCaught(); throw e; } } |
四、Retrofit流程总结 1. Retrofit对象的构建 Retrofit.Builder()...build():①构建OkHttpClient,目前Retrofit仅支持OkHttpClient;②构建Executor:优先根据用户提供的callBackExcecutor来构建,若用户没有提供,则提供defaultCallbackExecutor(其内部会获取MainLooper构建handler,execute方法直接handler.post(runnable),实现在主线程上的操作);③使用executor来构建adapterFactories集合,优先将用户提供的adapterFactory加入到其中,再加上defaultCallAdapterFactory(传入②创建的callbackExecutor,defaultCallAdapterFactory内部持有OkHttpCall,在其enqueue方法中的onResponse方法调用defaultCallbackExecutor.execute方法,从而实现线程切换操作);④最终使用Retrofit构造方法构建Retrofit实例对象 2. Retrofit接口方法的实现方式 retrofit.create(接口名.class):①create方法创建并返回动态代理对象实例,动态代理对象内部会拦截接口方法的调用②动态代理内部通过ServiceMethod将接口方法适配成HTTP Call,再构造对应的OkHttpCall,最后通过CallAdapter转换成Retrofit适用的call delegate(ExecutorCallbackCall)。 3. 使用动态代理(接口实现类)调用接口方法得到Call、使用call.enqueue进行异步请求:①调用接口方法时,动态代理对象(接口实现类)内部拦截;②调用call.enqueue,内部会调用ExecutorCallAdapter的enqueue方法,enqueue中onResponse方法调用defaultCallbackExecutor.execute方法,使用主线程Handler.post(runnable)从而实现线程切换操作。
更多相关文章
- android Qemu GPS 模块简明分析
- Android(安卓)Service两种启动方式详解(总结版)
- 几种判断应用(Android(安卓)App)前后台状态的方法
- Android热修复原理探索与实践
- Android之Activity生命周期浅析(一)
- Android中获取控件的宽度以及高度的几种方法
- [置顶] Android:在任意位置获取应用程序Context
- Android中Handler小例子
- Android(安卓)View相关-View的常用方法及使用区别