目录
一、Okhttp请求
示例代码:
private void testOkHttp() {
// step1
OkHttpClient client = new OkHttpClient();
// step2
Request request = new Request.Builder()
.url("https://www.google.com.hk")
.build();
// step3
Call call = client.newCall(request);
// step4 发送网络请求,获取数据,进行后续处理
call.enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
}
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {
}
});
}
上面示例代码解析:
step1:创建 HttpClient 对象,也就是构建一个网络类型的实例,一般会将所有的网络请求使用同一个单例对象。
step2:构建 Request,也就是构建一个具体的网络请求对象,具体的请求 url,请求头,请求体等等。
step3:构建请求 Call,也就是将具体的网络请求与执行请求的实体进行绑定,形成一个具体的正式的可执行体。
step4:后面就是进行网络请求了,然后处理网络请求的数据。
总结一下:
OkHttp 的意义:OkHttp 是基于 Http 协议封装的一套请求客户端,虽然它可以开线程,但根本上它更偏向真正的请求,跟 HttpClient,HttpUrlConnection 的职责是一样的。
OkHttp 的职责:OkHttp 主要负责 socket 部分的优化,比如多路复用,buffer 缓存,数据压缩等等。
OkHttp 给用户留下的问题:
1)用户网络请求的接口配置繁琐,尤其是需要配置请求 body,请求头,参数的时候;
2)数据解析过程需要用户手动拿到 responsebody 进行解析,不能复用;
3)无法适配自动进行线程的切换;
4)万一存在网络嵌套网络请求就会陷入“回调陷阱”
二、Retrofit 请求
示例代码使用:
导入相关包:
// Retrofit的依赖
implementation 'com.squareup.retrofit2:retrofit:2.1.0'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
代码示例
// step1 建立一个Retrofit对象,配置好Retrofit类的成员变量
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.wanandroid.com") //网络请求的url地址
.addConverterFactory(GsonConverterFactory.create(new Gson()))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
// step2 创建一个ISharedListService接口类的对象,create函数内部使用了动态代理来创建接口
//对象,这样的设计可以让所有的访问请求都被代理
ISharedListService sharedListService = retrofit.create(ISharedListService.class);
// step3 调用getSharedList的时候,在动态代理里面,会存在一个函数 getSharedList,
// 这个函数里面会调用 invoke,这个 invoke 函数也就是retrofit 里面的 invoke 函数
// 目的:将接口转换成网络请求
Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1); //这里返回的是ExecutorCallbackCall对象
// step4
sharedListCall.enqueue(new Callback<SharedListBean>(){
@Override
public void onResponse(Call<SharedListBean> call, Response<SharedListBean> response) {
if (response.isSuccessful()) {
System.out.println(response.body().toString());
}
}
@Override
public void onFailure(Call<SharedListBean> call, Throwable t) {
t.printStackTrace();
}
})
上面示例代码解析:
step1: 创建 retrofit 对象,构建一个网络请求的载体对象,和 OkHttp 构建 OKHttpClient 对象有一样的意义,只不过 retrofit 在 build 的时候有非常多的初始化内容,这些内容可以为后面网络请求提供准备,如准备 线程转换Executor, Gson convert,RxjavaCallAdapter。
step2:Retrofit 的精髓,为统一配置网络请求完成动态代理的设置。
step3:构建具体网络请求对象 Request(service), 在这个阶段要完成的任务:
1)将接口中的注解翻译成对应的参数;
2)确定网络请求参数的返回值 response 类型以及对应的转换器;
3)将 OkHttp 的 Request 封装成为 Retrofit 的 OkhttpCall。
总的来说,就是根据请求 service 的 interface 来封装 Okhttp 请求 Request。
step4: 后面就进行网络请求,然后处理网络请求的数据。
其中:
baseUrl:网络请求的url地址
callFactory:网络请求工厂
callbackExecutor:回调方法执行器
adapterFactories:网络请求适配器工厂的集合
coverterFatories:数据转换器工厂的集合
总结一下:
Retrofit 主要负责应用层面的封装,就是说主要面向开发者,方便使用,比如请求参数,响应数据的处理,错误处理等等。
Retrofit 封装了具体的请求,线程切换以及数据转换。
网上一般都推荐 RxJava + Retrofit + OkHttp 框架,Retrofit 负责请求的数据和请求的结果,使用接口的方式呈现,OkHttp 负责请求的过程,Rxjava 负责异步,各种线程之间的切换,用起来非常便利。
ISharedListService.java
public interface ISharedListService {
@GET("user/{userid}/share_articles/{pageid}/json")
Call<SharedListBean> getSharedList(@Path("userid") int it, @Path("pageid") int pageid);
}
retrofit是如何封装请求的
大体的网络流程是一致的,毕竟都是通过okhttp进行网络请求。主要的步骤都是:创建网络请求实体client -> 构建真正的网络请求 -> 将网络请求方案与真正的网络请求实体结合构成一个请求Call -> 执行网络请求 -> 处理返回数据 -> 处理 Android 平台的线程问题。
在上图中,我们看到的对比最大的区别是:
1)okhttp创建的是OkHttpClient,然而retrofit创建的是Retrofit实例
2)构建Request的流程,retrofit是通过注解来进行适配
3)配置Call的过程中,retrofit是利用Adapter适配的OkHttp的Call
4)相对okhttp,retrofit会对responseBody进行自动的Gson解析
5)相对okhttp,retrofit会自动的完成线程的切换
三、Retrofit的构建过程
Retrofit 通过build模式来生成一个Retrofit对象,通过代码我们知道,Retrofit默认会使用Okhttp来发送网络请求,当然,我们也可以自己定制。
执行step1中的build()操作,进入下面的build流程
Retrofit.java
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 代码1
// 默认只支持 okhttp 请求,不支持 httpurlconnection 和 httpclient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 代码2
// 添加一个线程管理 Executor, okhttp 切换线程需要手动处理,但是 retrofit
//不需要,就是因为这个 Executor 的存在,其实它是handler
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 代码3
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // 添加一个默认的callAdapterFatory
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
其中,build流程采用构建/建造者设计模式和外观/门面设计模式。
1: 在代码1处
初始化构建call的工厂,但是这个地方直接就是使用了okhttp的call,没有使用到工厂设计模式去添加构建httpclient 或者 httpurlconnection的方法来创建call,说明retrofit已经铁下心只支持okhttp创建call请求。
此次调用,目的就是创建一个OkHttpClient,换句话说,这里的调用就是生产Okhttp网络请求需要的请求Call,以备后面进行真正的网络请求。
2:在代码2处
网络请求需要在子线程中执行,那么就需要线程管理,所有就有了代码2的存在,深入源码后发现,这个地方就是运用handler进行线程切换,当网络请求回来了进行线程切换,可以看下面的源码:
Platform.java
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
所以,此次调用,目的是构建一个用handler封装的Executor,以备后面进行网络请求成功后的线程切换用。
3:在代码3处
设置默认CallAdapterFactory
在此添加的CallAdapterFactory属于系统默认的,当然,我们可以添加RxJavaCallAdapterFactory。默认的CallAdapterFactory是ExecutorCallAdapter类的对象,在Platform.java Class里面可以梳理出来
Platform.java
CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor != null) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
return DefaultCallAdapterFactory.INSTANCE;
}
所以构建的Retrofit都是用于进行后面请求的需要的内容的一个准备工作。也就是封装OkHttp需要的准备工作。
最后new 了一个Retrofit对象
Retrofit.java
public final class Retrofit {
// 网络请求配置对象(对网络请求接口中方法注解进行解析后得到的对象)
// 作用:存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
// 网络请求器的工厂
// 作用:生产网络请求器(Call)
// Retrofit 是默认使用okhttp
final okhttp3.Call.Factory callFactory;
// 网络请求的url地址
final HttpUrl baseUrl;
// 数据转换器工厂的集合
// 作用:放置数据转换器工厂
// 数据转换器工厂作用:生产数据转换器(converter)
final List<Converter.Factory> converterFactories;
// 网络请求适配器工厂的集合
// 作用:放置网络请求适配器工厂
// 网络请求适配器工厂作用:生产网络请求适配器(CallAdapter)
final List<CallAdapter.Factory> adapterFactories;
// 回调方法执行器
final @Nullable Executor callbackExecutor;
// 标志位
// 作用:是否提前对业务接口中的注解进行验证转换的标志位
final boolean validateEagerly;
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
...
}
四、Retrofit构建IxxxService对象的过程(Retrofit.create())
看下面的代码:
ISharedListService sharedListService = retrofit.create(ISharedListService.class);
Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1);
上面两行代码需要连起来才能正确的被阅读,因为,在create里面是使用了动态代理的技术方案,而动态代理是运行时生效的
执行step2,调用Retrofit的create()方法,create函数内部使用了动态代理来创建接口对象,这样的设计可以让所有的访问请求都被代理
create()方法里面采用动态代理设计模式,这个里面采用AOP切面编程思想
Retrofit.java
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(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, @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);
}
// 默认情况下,java的接口是不能够有默认实现的,但是Java8 可以默认实现
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 根据方法生成一个ServiceMethod对象(内部会将生成的ServiceMethod放入缓存中)
// 如果已经生成过则直接从缓存中获取
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
// 根据ServiceMethod对象和请求参数生成一个OkHttpCall对象,
// 这个OkHttpCall能够调用OkHttp的接口发起网络请求
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
// 调用serviceMethod 的 callAdapter 的 adapter方法,并传入 okhttpCall,返回一个对象,
// 这个的目的主要是为了适配返回类型,其内部会对OkHttpCall对象进行包装
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
1)Retrofit的create方法通过动态代理的模式,生成了实现具体的网络请求接口的对象,并在InvocationHandler的invoke方法中统一处理网络请求接口实体对象的方法;2)invoke方法会通过方法构造一个ServiceMethod对象,并将其放入缓存中;3)然后根据ServiceMethod对象和网络请求的参数args去构造一个OkhttpCall对象;4)最后调用serviceMethod的callAdapter的adapter方法,传入将OkHttpCall对象,callAdapter的目的主要是为了适配OkHttpCall对象,其内部会对OkHttpCall对象进行包装,生成对应返回类型的对象。
4.1 动态代理
动态代理的原理主要是在运行时动态生成代理类,然后根据代理类生成一个代理对象,在这个代理对象的方法中又会调用InvocationHandler的invoke来转发对方法的处理。
在使用retrofit的时候,对每一个网络请求的产生都必须要先调用create函数,也就意味着,我们的请求都是通过代理类来进行处理的。但是代理类具体的代理行为是发生在哪里呢?很明显,它并不是在create函数执行的时候,而是在使用具体的接口创建具体网络请求Call的时候,当调用具体网络请求Call的代码示例如下:
Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1);
在执行上面 代码的时候,它会走代码设计模式的InvocationHandler里面的invoke()函数,也就是所有的网络请求在创建具体网络请求Call的时候,都会走invoke, 从而我们可以在invoke里面进行各种行为的统一处理,比如:接口的统一处理,也就是注解的解读和网络请求参数的拼接。
在代码执行create()方法时,执行到Proxy.newProxInstance()时,在运行时会动态创建一个代理类对象类如ISharedListServiceProxy,并且该类实现了ISharedListService接口
代理类:
class ISharedListServiceProxy implement ISharedListService{
// toString();
// hashCode(); 等等一系列方法
...
// 接口方法
public void getSharedList(int it, int pageid) {
invocationHandler.invoke(it, pageid);
}
}
4.2 ServiceMethod
执行动态代理的invoke()方法,会执行 loadServiceMethod()方法
其实就将注解、参数都转化成网络请求Call的参数,一个请求对于一个ServiceMethod
Retrofit.java
ServiceMethod<?, ?> loadServiceMethod(Method method) {
// 为什么会缓存--》为了效率
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder<>(this, method).build(); // 采用建造者设计模式
serviceMethodCache.put(method, result);
}
}
return result;
}
loadServiceMethod首先会从缓存中获取ServiceMethod对象,如果没有,则通过Method和Retrofit对象构造一个ServiceMethod对象,并将其放入缓存中。
每一个method都有一个自己的ServiceMethod,这就意味着ServiceMethod是属于函数的,而不是类的。也就是我们定义的网络访问接口类,在接口类里面的每一个函数都会在反射阶段形成自己的serviceMethod。
ServiceMethod其实是用来存储一次网络请求的基本信息的,比如Host、URL、请求方法等,同时ServiceMethod还会存储用来适配OkHttpCall对象的CallAdapter。ServiceMethod的build方法会解读传入的Method,首先ServiceMethod会在CallAdapterFactory列表中寻找合适的CallAdapter来包装OkHttpCall对象的,这一步主要是根据Method的返回参数来匹配的,比如如果方法的返回参数是Call对象,那么ServiceMethod就会使用默认的CallAdapterFactory来生成CallAdapter,而如果返回对象是RxJava的Observable对象,则会使用RxJavaCallAdapterFactory提供的CallAdapter。如果build方法会解读Method的注解,来获得注解上配置的网络请求信息,比如请求方法、URL、Header等。
ServiceMethod.java
final class ServiceMethod<R, T> {
// Upper and lower characters, digits, underscores, and hyphens, starting with a character.
static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);
// 网络请求工厂 也就是okhttp的网络请求
final okhttp3.Call.Factory callFactory;
// 网络请求适配器 把call请求适配各个平台
final CallAdapter<R, T> callAdapter;
// 网络基地址
private final HttpUrl baseUrl;
// 数据转换器
private final Converter<ResponseBody, R> responseConverter;
// 网络请求的http方法 比如 get、post方法
private final String httpMethod;
// 网络请求的相对地址 和 baseUrl 拼接起来就是实际地址
private final String relativeUrl;
// 请求头
private final Headers headers;
// 网络请求的 http 报文的 type
private final MediaType contentType;
// 三个标志位
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
// 方法参数的处理器 比如我们定义的方法 上面的 get 和后面的参数
private final ParameterHandler<?>[] parameterHandlers;
// 构建一系列的变量
ServiceMethod(Builder<R, T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
static final class Builder<T, R> {
final Retrofit retrofit;
final Method method;
final Annotation[] methodAnnotations;
final Annotation[][] parameterAnnotationsArray;
final Type[] parameterTypes;
Type responseType;
boolean gotField;
boolean gotPart;
boolean gotBody;
boolean gotPath;
boolean gotQuery;
boolean gotUrl;
String httpMethod;
boolean hasBody;
boolean isFormEncoded;
boolean isMultipart;
String relativeUrl;
Headers headers;
MediaType contentType;
Set<String> relativeUrlParamNames;
ParameterHandler<?>[] parameterHandlers;
Converter<ResponseBody, T> responseConverter;
CallAdapter<T, R> callAdapter;
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() {
callAdapter = createCallAdapter(); //查找能适配返回类型的CallAdapter
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?");
}
// 设置请求的数据适配器converter
responseConverter = createResponseConverter();
// 解读方法的注解,methodAnnotations表示方法上的所有注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this); // new了一个ServiceMethod
}
ServiceMethod 作用就是解析注解、解析请求的返回值这一系列过程
retrofit是对整个网络请求的一个保存,ServiceMethod是对某一个接口请求(具体的网络请求)的保存,就是从retrofit中所保存的一系列参数列表中找到对应的参数
4.3 okHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
我们知道,ServiceMethod封装了网络请求的基本信息,比如Host、URL等,我们根据ServiceMethod和请求参数args就可以确定本次网络请求的所有信息了,OkHttpCall主要是将这些信息封装起来,并调用OkHttp的接口去发送网络请求,这里,我们就将OkHttpCall看成是一个处理网络请求的类即可。
4.4 callAdapter
在retrofit中,invoke()里面的最后一行代码,
return serviceMethod.callAdapter.adapt(okHttpCall);
下面对这行代码的执行流程进行分析:
这条语句分两步进行分析:
第一步:首先先进行分析serviceMethod.callAdapter是在哪进行赋值的
ServiceMethod.java
public ServiceMethod build() {
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?");
}
responseConverter = createResponseConverter();
...
}
在执行loadServiceMethod()
的流程中,会执行到ServiceMethod类的build()
方法,从而对执行了createCallAdapter()
方法,并对callAdapter进行了赋值。
ServiceMethod.java
private CallAdapter<T, R> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations); //执行该条语句
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
执行retrofit.callAdapter()
语句继续往下流程
Retrofit.java
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
执行nextCallAdapter()
流程
Retrofit.java
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
// 从Factory中去取对应的CallAdapter
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = adapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
执行 CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
这条语句,返回对应的CallAdapter对象,其中adapterFactories是在执行step1流程的build()
语句会对该List列表进行添加数据
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
特别注意这个地方的callbackExecutor参数,其实是build()
语句里面进行new出来的。
Retrofit.java
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
转而执行Android平台下的defaultCallbackExecutor()
Platform.java
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
...
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
其实最后就是调用创建了一个Handler在主线程中执行后续的流程。
在回到adapterFactories.add()
操作,默认添加的数据是platform.defaultCallAdapterFactory(callbackExecutor)
,从而执行到Android平台的defaultCallAdapterFactory()
方法。
Platform.java
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
最后new了一个ExecutorCallAdapterFactory对象,也就是说adapterFactories.get(i)
获取的就是一个ExecutorCallAdapterFactory对象,执行adapterFactories.get(i).get(returnType, annotations, this)
就是执行到了ExecutorCallAdapterFactory的get()
方法。
ExecutorCallAdapterFactory.java
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
// 返回一个CallAdapter
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
第二步:再回到下面这条语句return serviceMethod.callAdapter.adapt(okHttpCall);
,执行adapte流程也就是执行了ExecutorCallAdapterFactory里面get()
方法里面的adapt()
方法,
@Override public Call<Object> adapt(Call<Object> call) {
// 将okhttpCall转换为ExecutorCallbackCall,这个地方采用适配器设计模式
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
最后就是新建了一个ExecutorCallbackCall对象。
也就是说serviceMethod.callAdapter.adapt()
返回给执行这条语句
Call<SharedListBean> sharedListCall = sharedListService.getSharedList(2, 1);
返回的是ExecutorCallbackCall对象(ExecutorCallbackCall 实现Call接口)
那么我们可以设想一下为什么Retrofit还要设计一个CallAdapter接口呢?
先来说一个客观事实,Retrofit真正使用okhttp进行网络请求的就是OkHttpCall这个类
曾提到了Call对象的创建是通过ServiceMethod.adapter()完成的,这里在看看该方法的源码:
ServiceMethod.adapter()方法:
T adapte(Call<R> call) {
return callAdapter.adapte(call);
}
通过上述源码可知,最终Call对象是调用CallAdapter.adapter(Call)方法创建的,那么CallAdapter及具体的Call对象又是如何生成的呢?
如果没有这个适配器模式,会出现上面情况?
很明显,没有适配器的时候此时我们网络请求的返回接口只能直接返回OkHttpCall,那么所有的网络请求都是用okhttpCall进行,这样的话就失去了retrofit封装网络请求call的意义了,譬如:RxjavaCallAdapterFactory就没有办法支持。
如果我们想要返回的不是Call呢?比如Rxjava的Observable,这种情况下该怎么办呢?
适配器模式在此发挥了其应用的作用
将网络请求的核心类OkHttpCall进行适配,你需要什么类型的数据就通过适配器适配,返回适配后的对象就是了,正是这种CallAdapter接口的设计,使得我们在使用Retrofit的时候可以自定义我们想要的返回类型。此接口的设计也为Rxjava的扩展使用做了很好的基础。
五、Retrofit网络请求操作
执行step4步骤的sharedListCall.enqueue()步骤,也就是执行了ExecutorCallbackCall的enqueue()方法
ExecutorCallAdapterFactory.java
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) {
checkNotNull(callback, "callback == null");
// delegate就是okHttpCall对象
delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
// 这条语句在主线程中执行
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);
}
});
}
});
}
其中,delegate变量是从执行这条语句return serviceMethod.callAdapter.adapt(okHttpCall);
传递过来的参数okHttpCall,delegate.enqueue()就相当于执行OkHttpCall对象的enqueue()方法。
OkHttpCall.java
@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 {
// 代码1
// 创建一个真正的call对象
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
if (failure != null) {
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
// 代码2
//执行okhttp3 Call的enqueue,也就是okhttp的enqueue流程
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
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:在代码1处
执行createRawCall()方法
OkHttpCall.java
private okhttp3.Call createRawCall() throws IOException {
// 通过serviceMethod保存的参数去构建一个okhttp的request
Request request = serviceMethod.toRequest(args);
// 构建一个okhttp的call
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
通过调用serviceMethod.toRequest()方法将serviceMethod中保存的参数去构建一个okhttp的request请求
ServiceMethod.java
Request toRequest(@Nullable Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
RequestBuilder.java
Request build() {
HttpUrl url;
HttpUrl.Builder urlBuilder = this.urlBuilder;
if (urlBuilder != null) {
url = urlBuilder.build();
} else {
// No query parameters triggered builder creation, just combine the relative URL and base URL.
//noinspection ConstantConditions Non-null if urlBuilder is null.
url = baseUrl.resolve(relativeUrl);
if (url == null) {
throw new IllegalArgumentException(
"Malformed URL. Base: " + baseUrl + ", Relative: " + relativeUrl);
}
}
RequestBody body = this.body;
if (body == null) {
// Try to pull from one of the builders.
if (formBuilder != null) {
body = formBuilder.build();
} else if (multipartBuilder != null) {
body = multipartBuilder.build();
} else if (hasBody) {
// Body is absent, make an empty body.
body = RequestBody.create(null, new byte[0]);
}
}
MediaType contentType = this.contentType;
if (contentType != null) {
if (body != null) {
body = new ContentTypeOverridingRequestBody(body, contentType);
} else {
requestBuilder.addHeader("Content-Type", contentType.toString());
}
}
return requestBuilder
.url(url)
.method(method, body)
.build();
}
2:在代码2处
执行call.enqueue(),call是 okhttp3.Call对象,也就是最后执行到okhttp的enqueue流程。
1.OkHttpCall 对 OkHttp3 Call进行了封装,ExecutorCallbackCall对OkHttpCall进行了封装,ExecutorCallbackCall功能增强的地方是调用
callbackExecutor.execute()
进入主线程中执行callback。这个地方采用了装饰器设计模式
2.在执行new ExecutorCallbackCall<>(callbackExecutor, call)
的过程,就是将okhttpCall转换成ExecutorCallbackCall的过程,这个地方采用了适配器设计模式
3. 如果这条语句Call<SharedListBean> getSharedList(@Path("userid") int it, @Path("pageid") int pageid)
,需要方法的返回类型为Rxjava的Observable对象
而不是Call<SharedListBean>
,这个过程也采用适配器设计模式
4. 在进行Rxjava进行转换的时候,包含ResponseCallAdapter、SimpleCallAdapter、ResultCallAdapter
,根据返回结果的不同使用不同的适配器,选择不同适配器算法的过程是采用策略设计模式
一般的Retrofit网络请求的操作是指Call.execute() & Call.enqueue()的过程,这个过程才是真正的网络请求,因为,网络配置,请求地址配置,Call适配,网络请求requestBody & 返回值responseBody转化适配准备工作都已经完成。
sharedListCall.enqueue(new Callback()...);
sharedListCall.execute();
在进行网络请求执行的时候,基本上就是调用,ServiceMethod中设置的各个内容如:
1)OkHttpCall进行网络请求,实则是进行okhttp的网络请求;
2)利用converter进行网络请求数据的转换,一般是Gson();
3)利用rxjava observable构建rxjava类型的责任链访问方案,并进行线程切换;
4)如果没有rxjava的添加,那么就使用默认的callAdapter里面的callbackExecutor进行线程的切换,进行网络请求。
整体网络请求的流程图: