Retrofit,是当下最热的一个网络请求库,今天我们来探索它的运行机制。
第一部分:创建
在探索机制前我们先来创建一个Retrofit。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://fanyi.youdao.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
这里很明了,Retrofit的实例化用的是建造者模式。我们先看 的步骤吧
步骤1
<-- Retrofit类 -->
public final class Retrofit {
// 网络请求的url地址
private final HttpUrl baseUrl;
/*
* 网络请求器的工厂
* 作用:生产网络请求器(Call)
* Retrofit是默认使用okhttp
*/
private final okhttp3.Call.Factory callFactory;
/*
* 网络请求适配器工厂的集合
* 作用:放置网络请求适配器工厂
* 网络请求适配器工厂作用:生产网络请求适配器(CallAdapter)
*/
private final List<CallAdapter.Factory> adapterFactories;
/*
* 数据转换器工厂的集合
* 作用:放置数据转换器工厂
* 数据转换器工厂作用:生产数据转换器(converter)
*/
private final List<Converter.Factory> converterFactories;
// 回调方法执行器
private final Executor callbackExecutor;
<-- Retrofit类的构造函数 -->
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories);
this.adapterFactories = unmodifiableList(adapterFactories);
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
...
// 仅贴出关键代码
}
我们看到这里面有几个成员变量
CallFactory:网络请求工厂,默认是OkHttp
ConverterFactories:是ConverterFactory数据转换器工厂的集合。
ConverterFactory:数据转换器工厂,生产Converter,例如GsonConverterFactory
Converter:进行数据的转换,例如GsonConverterFactory生产的Convert就对Gson数据转化成对应的Bean类型
AdapterFactories:是callAdapterFactory网络请求适配器工厂的集合。
CallAdapterFactory:生产的是CallAdapter
CallAdapter:网络请求执行器,例如Retrofit默认的ExecutorCallAdapterFactory生产的CallAdapter,即创建Service中的Call,如果是RxJavaCallAdapterFactory就生产Rxjava,及创建Service中的Observable
由此可以看出第二个设计模式:工厂模式,Retrofit根据传入的工厂的种类生产对应的产品。
- callbackExecutor:回调方法执行器
在Retrofit中提供了四种CallAdapterFactory: ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、Java8CallAdapterFactory、RxJavaCallAdapterFactory, 采用了策略模式
接下来分析
<-- Builder类-->
public static final class Builder {
private Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private List<Converter.Factory> converterFactories = new ArrayList<>();
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;
// 从上面可以发现, Builder类的成员变量与Retrofit类的成员变量是对应的
// 所以Retrofit类的成员变量基本上是通过Builder类进行配置
<-- 步骤1 -->
// Builder的构造方法(无参)
public Builder() {
this(Platform.get());
}
...
}
class Platform {
<-- 步骤2 -->
static Platform get() {
return PLATFORM;
}
<-- 步骤3 -->
private static final Platform PLATFORM = findPlatform();
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
<-- 步骤4 返回Android平台对应的Platform-->
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
...
return new Platform();
}
...
}
<-- 步骤5 Android平台对应的Platform-->
static class Android extends Platform {
@Override
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
// 创建默认的网络请求适配器工厂
}
@Override
public Executor defaultCallbackExecutor() {
// 返回一个默认的回调方法执行器
// 该执行器作用:切换线程(子->>主线程),并在主线程(UI线程)中执行回调方法
return new MainThreadExecutor();
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
// 获取与Android 主线程绑定的Handler
@Override
public void execute(Runnable r) {
handler.post(r);
// 该Handler是上面获取的与Android 主线程绑定的Handler
// 在UI线程进行对网络请求返回数据处理等操作。
}
}
}
<-- 步骤6 -->
// Builder类的构造函数2(有参)
public Builder(Platform platform) {
this.platform = platform;
//创建一个数据转换器工厂BuiltInConverters,并添加到converterFactories中
converterFactories.add(new BuiltInConverters());
}
总结:在Builder()这个步骤里
- 创建了默认的回调执行器:defaultCallbackExecutor(在Platform)
- 创建了默认的CallAdapterFactory:ExecutorCallAdapterFactory(在Platform)
- 创建了默认的ConverterFactory:BuiltInConverters
特别注意,这里只是设置了默认值,但未真正配置到具体的Retrofit类的成员变量当中, 真正配置将是后面的build里面。在build中,会调用platform的defaultCallbackExecutor()方法,创建defaultCallbackExecutor,并把它作为参数调用defaultCallAdapterFactory()创建ExecutorCallAdapterFactory
<-- 步骤1 -->
public Builder baseUrl(String baseUrl) {
// 把String类型的url参数转化为适合OKhttp的HttpUrl类型
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
// 最终返回带httpUrl类型参数的baseUrl()
// 下面继续看baseUrl(httpUrl) ->> 步骤2
return baseUrl(httpUrl);
}
<-- 步骤2 -->
public Builder baseUrl(HttpUrl baseUrl) {
//把URL参数分割成几个路径碎片
List<String> pathSegments = baseUrl.pathSegments();
// 检测最后一个碎片来检查URL参数是不是以"/"结尾
// 不是就抛出异常
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
}
总结:
- 把String类的baseUrl转换成适合OKhttp的HttpUrl
我们先看GsonConverterFactory.create()
public final class GsonConverterFactory extends Converter.Factory {
<-- 步骤1 -->
public static GsonConverterFactory create() {
// 创建一个Gson对象
return create(new Gson()); ->>步骤2
}
<-- 步骤2 -->
public static GsonConverterFactory create(Gson gson) {
// 创建了一个含有Gson对象实例的GsonConverterFactory
return new GsonConverterFactory(gson); ->>步骤3
}
private final Gson gson;
<-- 步骤3 -->
private GsonConverterFactory(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
this.gson = gson;
}
}
所以,GsonConverterFactory.creat()是创建了一个含有Gson对象实例的GsonConverterFactory,并返回给addConverterFactory() 接下来看addConverterFactory()
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
总结:在这个阶段,创建了一个含有Gson对象实例的GsonConverterFactory并放入到数据转换器工厂converterFactories里
public Retrofit build() {
<-- 配置网络请求执行器(callFactory)-->
okhttp3.Call.Factory callFactory = this.callFactory;
/*
* 如果没指定,则默认使用okhttp
* 所以Retrofit默认使用okhttp进行网络请求
*/
if (callFactory == null) {
callFactory = new OkHttpClient();
}
<-- 配置回调方法执行器(callbackExecutor)-->
Executor callbackExecutor = this.callbackExecutor;
/*
* 如果没指定,则默认使用Platform检测环境时的默认callbackExecutor
* 即Android默认的callbackExecutor
*/
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
<-- 配置网络请求适配器工厂(CallAdapterFactory)-->
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
/*
* 向该集合中添加了platform中创建的CallAdapter.Factory请求适配器(添加在集合器末尾)
* 请求适配器工厂集合存储顺序:自定义1适配器工厂、自定义2适配器工厂...默认适配器工厂(ExecutorCallAdapterFactory)
*/
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
<-- 配置数据转换器工厂:converterFactory -->
/*
* 在Builder()中已经添加了内置的数据转换器BuiltInConverters()(添加到集合器的首位)
* 现在又插入了一个用户要的Gson的转换器 - GsonConverterFactory(添加到集合器的首二位)
* 数据转换器工厂集合存储的是:默认数据转换器工厂( BuiltInConverters)、自定义1数据转换器工厂(GsonConverterFactory)、自定义2数据转换器工厂....
*/
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
/*
* 1. 获取合适的网络请求适配器和数据转换器都是从adapterFactories和converterFactories集合的首位-末位开始遍历
* 因此集合中的工厂位置越靠前就拥有越高的使用权限
*/
// 最终返回一个Retrofit的对象,并传入上述已经配置好的成员变量
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
总结: Retrofit使用建造者模式通过Builder类建立了一个Retrofit实例,具体创建细节是配置了:
- 平台类型对象(Platform - Android)
- 网络请求的url地址(baseUrl)
- 网络请求工厂(CallFactory):OkHttpCall
- 回调方法执行器(callbackExecutor):defaultCallbackExecutor,默认回调方法执行器作用是:切换线程(子线程 - 主线程)
- 网络请求适配器工厂的集合(AdapterFactories):包括默认的工厂ExecutorCallAdapterFactory(利用defaultCallbackExecutor构建)和用户自己添加的工厂
- 数据转换器工厂的集合(ConverterFactories):包括默认的BuiltInConverters和用户自己添加的GsonConverterFactory
创建网络请求接口的实例
public interface AccessApi {
@GET("openapi.do?keyfrom=Yanzhikai&key=2032414398&type=data&doctype=json&version=1.1&q=car")
// 返回类型为Call<*>,*是解析得到的数据类型,即JavaBean
Call<JavaBean> getCall();
}
AccessApi NetService = retrofit.create(AccessApi.class);
create()方法运用的是动态代理,所有的操作最后都会被代理类的方法invoke中执行。
public <T> T create(final Class<T> service) {
...
/*
* 创建了网络请求接口的动态代理对象,即通过动态代理创建网络请求接口的实例 (并最终返回)
* 该动态代理是为了拿到网络请求接口实例上所有注解
*/
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, Object... args)
throws Throwable {
// invoke()的实现
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
可见create方法返回了一个 Proxy.newProxyInstance动态代理对象,当我们调用NetService的getCall()方法时,最终会调用InvocationHandler的invoke方法。 接下来我们看下loadServiceMethod(method)
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
// 设置线程同步锁
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
// 创建ServiceMethod对象前,先看serviceMethodCache有没有缓存之前创建过的网络请求实例
// 若没缓存,则创建 serviceMethod 对象
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
<-- ServiceMethod 类 -->
public final class ServiceMethod {
// 网络请求工厂
final okhttp3.Call.Factory callFactory;
// 网络请求适配器工厂
final CallAdapter<?> callAdapter;
// 具体创建是在new ServiceMethod.Builder(this, method).build()最后的build()中
/*
* Response内容转换器
* 作用:负责把服务器返回的数据(JSON或者其他格式,由 ResponseBody 封装)转化为 T 类型的对象;
*/
private final Converter<ResponseBody, T> responseConverter;
// 网络请求地址
private final HttpUrl baseUrl;
// 网络请求的相对地址
private final String relativeUrl;
// 网络请求的Http方法
private final String httpMethod;
// 网络请求的http请求头 键值对
private final Headers headers;
// 网络请求的http报文body的类型
private final MediaType contentType;
/*
* 方法参数处理器
* 作用:负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;
*/
private final ParameterHandler<?>[] parameterHandlers;
// 说明:从上面的成员变量可以看出,ServiceMethod对象包含了访问网络的所有基本信息
<-- ServiceMethod 类的构造函数 -->
ServiceMethod(Builder<T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.responseConverter = builder.responseConverter;
this.baseUrl = builder.retrofit.baseUrl();
this.relativeUrl = builder.relativeUrl;
this.httpMethod = builder.httpMethod;
this.headers = builder.headers;
this.contentType = builder.contentType; .
this.hasBody = builder.hasBody; y
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
public 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() {
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器
callAdapter = createCallAdapter(); -- >关注点1
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取该网络适配器返回的数据类型
responseType = callAdapter.responseType();
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的数据转换器
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
/*
* 解析网络请求接口中方法的注解
* 主要是解析获取Http请求的方法
* 注解包括:DELETE、GET、POST、HEAD、PATCH、PUT、OPTIONS、HTTP、retrofit2.http.Headers、Multipart、FormUrlEncoded
*/
...
// 获取当前方法的参数数量
int parameterCount = parameterAnnotationsArray.length;
/*
* 为方法中的每个参数创建一个ParameterHandler<?>对象并解析每个参数使用的注解类型
* 该对象的创建过程就是对方法参数中注解进行解析
* 这里的注解包括:Body、PartMap、Part、FieldMap、Field、Header、QueryMap、Query、Path、Url
*/
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
总结
- 根据返回值类型和方法标注从Retrofit对象的的网络请求适配器工厂集合和内容转换器工厂集合中分别获取到该方法对应的网络请求适配器和Response内容转换器;
- 根据方法的标注对ServiceMethod的域进行赋值
- 最后为每个方法的参数的标注进行解析,获得一个ParameterHandler<?>对象 该对象保存有一个Request内容转换器——根据参数的类型从Retrofit的内容转换器工厂集合中获取一个Request内容转换器或者一个String内容转换器。
<-- 关注点1:createCallAdapter() 网络请求执行器-->
private CallAdapter<?> createCallAdapter() {
// 获取网络请求接口里方法的返回值类型
Type returnType = method.getGenericReturnType();
// 获取网络请求接口接口里的注解
Annotation[] annotations = method.getAnnotations();
try {
// 根据网络请求接口方法的返回值和注解类型,从Retrofit对象中获取对应的网络请求适配器
return retrofit.callAdapter(returnType, annotations);
// 下面会详细说明retrofit.callAdapter() -- >关注点2
}
...
<-- 关注点2:retrofit.callAdapter() -->
public CallAdapter<?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
/*
* 创建 CallAdapter 如下
* 遍历 adapterFactories 集合寻找合适的工厂(该工厂集合在第一步构造 Retrofit 对象时进行添加(第一步时已经说明))
* 从AdapterFactories中遍历它的元素CallAdapterFactory,获得CallAdapterFactory所生产的CallAdapter
* 如果最终没有工厂提供需要的 CallAdapter,将抛出异常
*/
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
<-- 关注点3:createResponseConverter() -->
private Converter<ResponseBody, T> createResponseConverter() {
Annotation[] annotations = method.getAnnotations();
try {
// responseConverter 还是由 Retrofit 类提供 -->关注点4
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) {
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
<-- 关注点4:responseBodyConverter() -->
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
int start = converterFactories.indexOf(skipPast) + 1;
/*
* 从ConverterFactories中遍历它的元素ConverterFactory,获得ConverterFactory所生产的Converter
* 遍历 Converter.Factory 集合并寻找合适的工厂(该工厂集合在构造 Retrofit 对象时进行添加(第一步时已经说明))
* 由于构造Retroifit采用的是Gson解析方式,所以取出的是GsonResponseBodyConverter
* Retrofit - Converters 还提供了 JSON,XML,ProtoBuf 等类型数据的转换功能
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
// 继续看responseBodyConverter() -->关注点5
}
<-- 关注点5:responseBodyConverter() -->
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
// 根据目标类型,利用 Gson#getAdapter 获取相应的 adapter
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
// 做数据转换时调用 Gson 的 API 即可。
final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
private final Gson gson;
private final TypeAdapter<T> adapter;
GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
this.gson = gson;
this.adapter = adapter;
}
@Override
public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}
以上就是获得ServiceMethod的过程,别忘了我们的create()方法还有接下来两个步骤
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
<--OkHttpCall类 -->
public class OkHttpCall {
// 含有所有网络请求参数信息的对象
private final ServiceMethod<T> serviceMethod;
// 网络请求接口的参数
private final Object[] args;
// 实际进行网络访问的类
private okhttp3.Call rawCall;
// 几个状态标志位
private Throwable creationFailure;
private boolean executed;
private volatile boolean canceled;
<--OkHttpCall构造函数 -->
public OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
// 传入了配置好的ServiceMethod对象和输入的请求参数
this.serviceMethod = serviceMethod;
this.args = args;
}
将第二步创建的OkHttpCall对象传给第一步创建的serviceMethod对象中对应的网络请求适配器的adapt()
return serviceMethod.callAdapter.adapt(okHttpCall);
/*
* 返回对象类型:Android默认的是Call<>;若设置了RxJavaCallAdapterFactory
* ,返回的则是Observable<>,这里就用默认的Call来讲解
*/
<-- adapt()详解-->
public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.delegate = delegate;
// 传入上面定义的回调方法执行器,用于进行线程切换
this.callbackExecutor = callbackExecutor;
}
采用了装饰模式:ExecutorCallbackCall = 装饰者,而里面真正去执行网络请求的还是OkHttpCall
使用装饰模式的原因:希望在OkHttpCall发送请求时做一些额外操作。这里的额外操作是线程转换,即将子线程切换到主线程
- OkHttpCall的enqueue()是进行网络异步请求的:当你调用OkHttpCall.enqueue()时,回调的callback是在子线程中,需要通过Handler转换到主线程进行回调。ExecutorCallbackCall就是用于线程回调;
- 当然以上是原生Retrofit使用的切换线程方式。如果你用Rxjava,那就不会用到这个ExecutorCallbackCall而是RxJava的Call,此处不过多展开
总结,在create的过程中,创建了一个动态代理,根据Service中方法对应产生一个ServiceMethod,它几乎包含了方法的所有信息,还根据方法的具体参数从对应的工厂集合中获取对应工厂,生产对应的产品,例如:从AdapterFactories里获取与参数对应的CallAdapterFactory,再从该CallAdapterFactory中获取CallAdapter;从ConverterFactories获取与参数对应的ConverterFactory,再从该ConverterFactory里获取Converter。
最后会利用这个ServiceMethod构建一个OkHttpCall,再获取ServiceMethod选择的CallAdapter,利用CallAdapter的adapt方法,该方法会返回一个call<>,每个CallAdapter中都有对应的call<>,Android默认的是Call<>,若设置了RxJavaCallAdapterFactory,返回的则是Observable<>。
原生的Retrofit的CallAdapter由ExecutorCallAdapterFactory生产(在前面Retorfit的build()中有说到),由于ExecutorCallAdapterFactory是传入了defaultCallbackExecutor的,加上adapt(okHttpCall),所以这个CallAdapter的adapt(okHttpCall)会获取到一个包含了一个既包含OkHttpCall,又包含defaultCallbackExecutor的Call<>——ExecutorCallbackCall,它将执行okHttpCall里的方法,又执行defaultCallbackExecutor进行线程切换,所以是装饰者模式。(默认情况,Rxjava不分析)
Call<JavaBean> call = NetService.getCall();
- NetService对象实际上是动态代理对象Proxy.newProxyInstance()(前面已说明),并不是真正的网络请求接口创建的对象
- 当NetService对象调用getCall()时会被动态代理对象Proxy.newProxyInstance()拦截,然后调用自身的InvocationHandler # invoke()
- invoke(Object proxy, Method method, Object… args)会传入3个参数:Object proxy:(代理对象)、
- Method method(调用的getCall())
- Object… args(方法的参数,即getCall()中的)
- 接下来利用Java反射获取到getCall()的注解信息,配合args参数创建ServiceMethod对象。
- 接下来就是返回OkHttp.Call类型的Call对象,可能是Call<>,可能是Observable<>一切看你的选择
发送请求
前面是
AccessApi NetService = retrofit.create(AccessApi.class);
在调用NetService的方法时,我们是
Call<JavaBean> call = NetService.getCall();
//当然也可能是
Observable<JavaBean> call = NetService.getCall();
就以前一种为例子,我们最后会调用call.execute()的情况 ,或call.enqueue()。由于这个call是ExecutorCallbackCall,它的execute()、enqueue()会调用它包含的okokHttpCall的execute()、enqueue()。
我们先看下call.execute()的情况
Response<JavaBean> response = call.execute();
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
// 设置同步锁
synchronized (this) {
call = rawCall;
if (call == null) {
try {
// 步骤1:创建一个OkHttp的Request对象请求 -->关注1
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
// 步骤2:调用OkHttpCall的execute()发送网络请求(同步)
// 步骤3:解析网络请求返回的数据parseResponse() -->关注2
return parseResponse(call.execute());
}
<-- 关注1:createRawCall() -->
private okhttp3.Call createRawCall() throws IOException {
// 从ServiceMethod的toRequest()返回一个Request对象
Request request = serviceMethod.toRequest(args);
// 根据serviceMethod和request对象创建 一个okhttp3.Call
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
<-- 关注2:parseResponse()-->
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
// 收到返回数据后进行状态码检查
int code = rawResponse.code();
if (code < 200 || code >= 300) {
}
if (code == 204 || code == 205) {
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
/* 等Http请求返回后 & 通过状态码检查后,将response body传
* 入ServiceMethod中,ServiceMethod通过调用Converter接口(之前设置
* 的GsonConverterFactory)将response body转成一个Java对象,即解析返回
* 的数据
*/
T body = serviceMethod.toResponse(catchingBody);
// 生成Response类
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
... // 异常处理
}
}
- ServiceMethod几乎保存了一个网络请求所需要的数据
- 发送网络请求时,OkHttpCall需要从ServiceMethod中获得一个Request对象
解析数据时,还需要通过ServiceMethod使用Converter(数据转换器)转换成Java对象进行数据解析
- 为了提高效率,Retrofit还会对解析过的请求ServiceMethod进行缓存,存放在Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();对象中
我们再看下call.enqueue()的情况
call.enqueue(new Callback<JavaBean>() {
@Override
public void onResponse(Call<JavaBean> call, Response<JavaBean> response) {
System.out.println(response.isSuccessful());
if (response.isSuccessful()) {
response.body().show();//UI操作
}
else {
try {
System.out.println(response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
} ;
}
}
<-- call.enqueue()解析 -->
@Override
public void enqueue(final Callback<T> callback) {
delegate.enqueue(new Callback<T>() {
// 使用静态代理 delegate进行异步请求 ->>分析1
@Override
public void onResponse(Call<T> call, final Response<T> response) {
// 步骤4:线程切换,从而在主线程显示结果
callbackExecutor.execute(new Runnable() {
/*
* 最后Okhttp的异步请求结果返回到callbackExecutor
* callbackExecutor.execute()通过Handler异步回调将结果传回到
* 主线程进行处理(如显示在Activity等等),即进行了线程切换
* 具体是如何做线程切换 ->>分析2
*/
@Override
public void run() {
if (delegate.isCanceled()) {
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);
}
});
}
});
}
<-- 分析1:delegate.enqueue()解析 -->
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
Throwable failure;
/* 步骤1:创建OkHttp的Request对象,再封装成OkHttp.call
* delegate代理在网络请求前的动作:创建OkHttp的Request对象,再封装成OkHttp.call
*/
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
// 创建OkHttp的Request对象,再封装成OkHttp.call, 方法同发送同步请求,此处不作过多描述
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
/*
* 步骤2:发送网络请求
* 最终还是调用Okhttp.enqueue进行网络请求
*/
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
// 步骤3:解析返回数据
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
// 请回去上面分析1的起点
<-- 分析2:异步请求后的线程切换-->
// 线程切换是通过一开始创建Retrofit对象时Platform在检测到运行环境是Android时进行创建的:(之前已分析过)
static class Android extends Platform {
/*
* 创建默认的回调执行器工厂
* 如果不将RxJava和Retrofit一起使用,一般都是使用该默认的CallAdapter.Factory
*/
@Override
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
@Override
public Executor defaultCallbackExecutor() {
// 返回一个默认的回调方法执行器,该执行器负责在主线程(UI线程)中执行回调方法
return new MainThreadExecutor();
}
// 获取主线程Handler
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
// Retrofit获取了主线程的handler,然后在UI线程执行网络请求回调后的数据显示等操作。
handler.post(r);
}
}
/*
* 切换线程的流程:
* 回调ExecutorCallAdapterFactory生成了一个ExecutorCallbackCall对象
* 通过调用ExecutorCallbackCall.enqueue(CallBack)从而调用
* MainThreadExecutor的execute()通过handler切换到主线程处理返回结果(如显示在Activity等等)
* /
}