Retrofit2 源码分析

将一个Java接口翻译成一个Http请求,然后用OkHttp去发送这个请求

一 入口类 Retrofit   成员变量

private final  HttpUrl baseUrl;//网络请求基地址

private final ListconverterFactories;//数据转换器工厂集合

private final List adapterFactories;//网络请求适配器工厂集合

private final okhttp3.Call.Factory callFactory;//底层进行网络请求工厂

private final Executor callbackExecutor;//回调方法执行器

/ServiceMethod是对业务接口中方法的注解进行解析之后得到的对象,该对象包含了访问网络的除了方法参数值之外的所有必要信息;如数据转换器、网络请求适配器、网络请求工厂、基地址、Http方法等等。

private final Map serviceMethodCache =newLinkedHashMap<>();

Retrofit.bulid()方法 初始化 外观模式

二 动态代理

https://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 动态代理的机制

http://www.ibm.com/developerworks/cn/java/j-jtp08305.html 动态代理的Decorator

GitHubServiceservice = retrofit.create(GitHubService.class);

create方法就是返回了一个Proxy.newProxyInstance动态代理对象

动态代理是java中的字节码生成技术。通过接口生成代理类,并将代理类的实现交给InvocationHandler作为具体的实现 ,

动态代理作为 Decorator 

就是你要调用某个class方法的前后 ,你可以很方便的插入些你想要执行的额外代码

一个动态代理类可以充当所有接口的 Decorator 或 Proxy,这样就不用每个接口都编写一个具体的实现类

Call > repos = service.listRepos("octocat");

执行流程:

service对象其实是一个动态代理对象,并不是一个真正的GitHubService接口的implements产生的对象,当api对象调用listRepos方法时会被动态代理拦截,然后调用Proxy.newProxyInstance方法中的InvocationHandler对象的invoke方法。

invoke方法会传入3个参数:

Object proxy, 代理对象

Method method,调用的方法 listRepos

Object... args 方法参数 octocat

Retrofit里的动态代理比较巧妙。它不关心proxyd,只是单纯的为了拿到了这个method上所有的注解 生成ServiceMethod对象,生成的ServiceMethod对象和args构造生成了HttpCall  可以发起HTTP请求的类

总结:简化复杂的网络请求,通过动态代理的去处理解析与拼装HTTP请求


三 核心类 ServiceMethod

一个ServiceMethod对象对应于一个 API interface 的一个方法

主要成员变量

final okhttp3.Call.Factory callFactory; //负责创建 HTTP 请求

final CallAdapter callAdapter; //请求适配器  把retrofit2.Call转为T

private final Converter responseConverter;  负责把服务器返回的数据(JSON、XML、二进制或者其他格式,由ResponseBody封装)转化为T类型的对象

private final Headers headers; //请求头信息

private final ParameterHandler[ ] parameterHandlers;//负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数

初始化过程 build()方法

callAdapter= createCallAdapter();//将遍历一个CallAdapter.Factory列表,根据方法返回值类型和注解提供需要的网络请求适配器

responseType=callAdapter.responseType();

responseConverter= createResponseConverter();//;即根据方法返回值类型和注释从retrofit中获取对应的转换器

for(Annotation annotation :methodAnnotations) {

parseMethodAnnotation(annotation);//解析Method的注解 给ServiceMethod的成员变量赋值

}

for(intp =0;p < parameterCount;p++) {

...

parameterHandlers[p] = parseParameter(p,parameterType,parameterAnnotations);

//方法中的每个参数创建一个ParameterHandler对象,该对象的创建过程就对方法参数中的Body、PartMap、Part、FieldMap、Field等注解进行解析

}

核心:okhttp3.Call.Factory,CallAdapter.Factory和Converter.Factory三个工厂类,模块之间、类之间通过接口进行依赖,创建十么样的实现类交给工厂去处理,工厂同样也是接口,添加怎样的工厂,则在最初构造Retrofit对象时决定,各个模块之间完全解耦,每个模块只负责自己的责任

四 执行HTTP请求

4.1 OkHttpCall类中execute() 同步发起网络请求,执行分析

createRawCall()    

1调用了serviceMethod.toRequest(args)来创建okhttp3.Request对象,之前解析参数注解的parameterHandlers在这里给HTTP请求 设置参数传进入,最后RequestBuilder build()生成Request请求

2 再调用serviceMethod.callFactory.newCall(request)来创建okhttp3.Call,这里之前准备好的callFactory同样也派上了用场,由于工厂在构造Retrofit对象时可以指定,所以我们也可以指定其他的工厂,来使用其它的底层 HttpClient 实现。这里Retrofit2就和Okhttp结合起来了 网络请求的执行业务流程都交给Okhttp来处理

return parseResponse(call.execute());

调用okhttp3.Call#execute()来执行网络请求,这个方法是阻塞的,执行完毕之后将返回收到的响应数据。收到响应数据之后,进行状态码的检查,再调用serviceMethod.toResponse(catchingBody)来把响应数据转化成我们需要的数据类型对象。使用之前准备好的responseConverte转化数据。

4.2 enqueue(Callback callback) 异步执行

这里的异步交给了okhttp3.Call#enqueue(Callback responseCallback)来实现,并在它的 callback 中调用parseResponse解析响应数据,并转发给传入的 callback

五  CallAdapter 接口

请求的适配化OkHttpCall --Adapter--> RxJava/java8/UICallback

通过适配器实现OkHttpCall到其它类型(比如RxJava等第三方库)的适配转换

public Interface CallAdapter {

Type responseType();//该请求适配器返回的数据类型

 T adapt(Call call);//该请求适配器对原始Call的再次封装,如Call到Observable,

abstract class  Factory {

public abstract CallAdapter get(Type returnType, Annotation[] annotations, Retrofit retrofit);//获取网络请求适配器

protected    staticType getParameterUpperBound(intindex, ParameterizedType type) 

{returnUtils.getParameterUpperBound(index, type); }

protectedstaticClass getRawType(Type type) {returnUtils.getRawType(type); }

}

ExecutorCallAdapterFactory 是Retrofit默认实现  

该对象存储一个回调执行器,异步请求将相应的结果交给callbackExecutor回调执行器去执行Android平台Retrofit2会使用主线程handler构造一个ExecutorCallAdapterFactory,调用enqueue(Callback),callback回调会在主线程中回调

5.1 Retrofit2和RxJava的结合使用

1 RxJavaCallAdapterFactory类 

 RxJava对请求进行包装,它将根据网络请求生成一个Observable进行流式任务执行

getCallAdapter方法中对返回值的泛型类型进行了进一步检查,例如我们声明的返回值类型为Observable,泛型类型就是List,这里对retrofit2.Response和retrofit2.adapter.rxjava.Result进行了特殊处理,有单独的 adapter 负责进行转换,其他所有类型都由SimpleCallAdapter负责转换

2 SimpleCallAdapter#adapt方法

创建了一个Observable,传入了CallOnSubscribe类,同时使用了一个OperatorMapResponseToBodyOrError操作符,用来把retrofit2.Response转为我们声明的类型,或者错误异常类型

3 CallOnSubscribe#call方法

clone 了原来的 call,因为okhttp3.Call是只能用一次的,所以每次都是新 clone 一个进行网络请求;创建了一个叫RequestArbiter的 producer,把这个 producer 设置给 subscriber;

Producer机制 简单的理解

Subscriber 都是被动接收 Observable 传递 过来的数据,然后Subscriber做处理。

但要是 Observable 发得太多,Subscriber 处理不过来,那就有问题了,所以就有了一种 Subscriber 主动 pull 的机制,而这种机制就是通过 Producer 实现的。给 Subscriber 设置 Producer 之后(通过Subscriber#setProducer方法),Subscriber 就会通过 Producer 向上游根据自己的能力请求数据(通过Producer#request方法),而 Observable 收到请求之后再根据请求的量给 Subscriber 发数据。

RequestArbiter#request方法

执行call.execute() 获取到Response响应数据,并且发送给下游接收

Observable.lift(OperatorMapResponseToBodyOrError.instance())

lift操作符 负责接收原始的Observable发出的事件,并在response.body()并发送给下游。这里,body()返回的就是我们声明的泛型类型了

Call->Response->Observable  执行流程

1 Observable.subscribe,触发 API 调用的执行;

2 CallOnSubscribe#call,clone call,创建并设置 producer;

3 subscriber 被设置了 producer 之后调用RequestArbiter#request,在 request 中发起网络请求,把处理结果发给下游;

4 OperatorMapResponseToBodyOrError$1#onNext,把 response 的  body 发给下游

5 最终就到了我们 subscribe 时传入的回调里面了;

六    概括Retrofit2的话,借鉴了服务器编程中AOP思想,利用动态代理技术通过接口在运行时拦截方法,接着通过解析注解拼装HTTP请求;最后包装了OkHttpCall生成真正的请求类 发起网络请求, 通过抽象工厂让各个模块直接解耦,完成对原数据Respone的Conver,实现了对Rx、线程的Adapter ,

你可能感兴趣的:(Retrofit2 源码分析)