okhttp官网
okhttp github
retrofit官网
retrofit github
使用retrofit之前,必须先会基本使用okhttp来请求网络资源,才能理解retrofit的工作原理。
okhttp使用教程挺多的,参考:Android OkHttp完全解析 是时候来了解OkHttp了
okhttp简单用法示例如下:
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
private OkHttpClient okHttpClient = new OkHttpClient();
private void httpGet() {
Request request = new Request.Builder()
.url("http://www.163.com")
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
String htmlStr = response.body().string();
Log.d("API", htmlStr);
}
});
}
可以看到,请求一个网络url前,需要先构建出okhttp3.Request, okhttp3.Call, Retrofit的主线工作流程就是干这个的。构建出请求,丢给okhttp,然后取得返回数据,复杂的网络工作都交给okhttp来做。
本文分析源码所使用的版本
implementation 'com.squareup.okhttp3:okhttp:3.12.3'
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
下面从retrofit最简单的使用例子开始,暂时不使用RxJava, Gson等,避免增加复杂度,直接获取okhttp3.ResponseBody是最简单的写法了。
(retrofit的使用教程也挺多的,参考:Android Retrofit 2.0 的详细 使用攻略)
先定义一个接口ApiService:
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.GET;
public interface ApiService {
// @GET注解的作用:采用Get方法发送网络请求
// 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody>
@GET("/")
Call<ResponseBody> getNewsHot();
}
然后:
private OkHttpClient okHttpClient = new OkHttpClient();
private void retrofitGet() {
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl("http://www.163.com")
.build();
ApiService service = retrofit.create(ApiService.class);
retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();
newsHot.enqueue(new retrofit2.Callback<ResponseBody>() {
@Override
public void onResponse(retrofit2.Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
try {
Log.d("API", "response:"+response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(retrofit2.Call<ResponseBody> call, Throwable t) {
}
});
}
这里,神奇的事情发生了:retrofit.create(ApiService.class)
,传进去一个ApiService.class, 又返回一个ApiService service,然后service.getNewsHot().enqueue(new Callback…)就能获得数据了。上面总共10来行代码,其实底下很复杂,咱们来一点一点地抠代码进行学习。
首先,把retrofit源码下载下来,放进自己的项目中,方便断点,以及打印日志来观察。
下面来分析每一行代码:
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl("http://www.163.com")
.build();
先看Retrofit类的成员变量
public final class Retrofit {
/**
* 一个Map, 缓存了Method和类ServiceMethod的键值对
* Method是什么, 就是ApiService里面的getNewsHot等方法.
* ServiceMethod是什么,这里刚开始看源码,只需要知道它是跟Method一一对应的java类,
* 大概是用于将service里面的method转换成okhttp3.Request的就行了,后面要深入细看
*/
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
/**
* callFactory: Call生成工厂。谁可以生成Call请求啊,只有okhttp可以,retrofit本身只是将请求参数转换成Request,是没法直接生成Call的,
* 所以callFactory就是okHttpClient。 注意这里的Call是okhttp3中的
*/
final okhttp3.Call.Factory callFactory;
/**
* 网络请求的url地址,如 "http://www.163.com"
*/
final HttpUrl baseUrl;
/**
* callAdapterFactories:Call适配器工厂。就是要根据每个方法的返回值,比如Call<ResponseBody> getNewsHot();
* 这里的返回值就是Call<ResponseBody>, 在调用service.getNewsHot() 方法时,此适配器工厂用来返回一个实现
* Call<T>接口的对象, 如: retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();
* 注意这里的Call是retrofit中的
*/
final List<CallAdapter.Factory> callAdapterFactories;
/**
* 数据转换器工厂, 即返回的数据交给哪个转换器来转换。
* 这里要注意的是找到第一个适合的转换器就直接使用,后面的不会再使用, 所以添加时要注意顺序
*/
final List<Converter.Factory> converterFactories;
/**
* 回调方法执行器
*/
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
/**
* Retrofit 构造函数
*/
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
@Nullable Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
可以看到,我们必须先实例化一个Retrofit类对象,并将各个成员初始化,才能使用它。那么怎样生成这个对象并初始化它呢, 使用Builder构造模式:
Retrofit retrofit = new Retrofit.Builder()
继续看这个构造函数:
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories = new ArrayList<>();
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
Builder(Retrofit retrofit) {
...
}
Builder类的成员变量platform初始化为Platform的子类Android, 其实Platform就是一个普通的java类,里面定义了两个方法:
Executor defaultCallbackExecutor()
CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor)
这两个方法都已经被Platform的子类Android重写,目前就知道这么多就行了。
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
okHttpClient被赋值为Retrofit的成员变量callFactory, Call生成工厂,上面已说过。
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl("http://www.163.com")
设置Retrofit的成员变量baseUrl
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl("http://www.163.com")
.build();
重点来了!!! 调用build()来生成Retrofit对象:
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// ①
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
// ②
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
// ③
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);
// ⑤
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
①callFactory就是okhttpclient, 没啥好说的
② callbackExecutor=platform.defaultCallbackExecutor(),Executor是一个接口
public interface Executor {
void execute(Runnable command);
}
由Platform的子类Android实现, 就是用Handler在主线程执行一个Runnable,很常见的用法:
static class Android extends Platform {
@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);
}
}
}
③ 只需要知道callAdapterFactories这个list, 里面增加了一个对象就行了,这个对象实现了CallAdapter.Factory接口,做为默认的callAdapterFactory , 没继续往下读代码是看不懂它的作用的。
④ 增加了一项默认数据转换器 BuiltInConverters, 而converterFactories在这里是空的,忽略它。
⑤ 直接用构造函数生成Retrofit对象,结束。
折腾了半天, 才终于生成一个对象,就问你累不累??!!!
下面可以开始使用这个对象了
ApiService service = retrofit.create(ApiService.class);
用到了动态代理模式JAVA反射_代理, 这行代码简单, 任何人都能写出,下一行代码才是整个Retrofit的精华,就跟魔法一样,看到了就会觉得哇!哇!哇!,原来写代码还可以这样,简直不可思议,出神入化:
retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();
调用这行代码,实际就是调用动态代理里的InvocationHandler里面的方法:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this.target, args);
}
这里要开始思考了, 接下来的并不是普通的代码, 是大神写的,大神写的代码不是那么容易看懂的, 各种你没见过的代码技巧,极致优化,反射/注解, 复杂得一B,大神的脑回路都跟常人的不同,如果陷入代码细节里,估计一时半会都出不来了。所以我们要抓住主线来看,有的放矢,才不会迷失。
首先, 我们的目的是要创建一个实现了retrofit2.Call<T>接口的newsHot对象,T的实际类型为ResponseBody。那么在invoke()方法里面, 我们就应该返回一个实现了retrofit2.Call<ResponseBody>接口的对象。注意,这里说的要实现什么接口,返回什么类型, 都是我们看前面的代码处于程序员的视角才知道的,但在invoke()方法里面,只有三个参数(Object proxy, Method method, Object[] args), 所有的信息都只能从这三个参数中获得,这就必须通过反射和注解来获取这些信息。
现在来详细看invoke()方法里面的代码:
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
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 {
// 省略代码...
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
首先我们要获得一个ServiceMethod类,如果在serviceMethodCache缓存里没找到就生成一个:
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;
}
怎样生成ServiceMethod对象, 套路就跟前面生成Retrofit对象一样, 使用Builder构造模式。那么老规矩,先看ServiceMethod类的成员变量
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);
/**
* callFactory: 肯定引用了前面Retrofit对象的成员变量callFactory
*/
private final okhttp3.Call.Factory callFactory;
/**
* 这里要一定好好理解清楚,把该接口的英文注释读得明明白白。
* callAdapter的作用:Adapts a {@link Call} with response type {@code R} into the type of {@code T}.
* 就是将一个Call<R>转换成另一个东东T, 实际就是将Call<ResponseBody> 转换成 T
*/
private final CallAdapter<R, T> callAdapter;
/**
* baseUrl: 肯定引用了前面Retrofit对象的成员变量baseUrl,这里也可以推论出,每个Retrofit对象都有不同的baseUrl, 每个Retrofit对象下的方法
* 都应该共用同一个baseUrl, 接口ApiService内所有方法都应访问相同的baseUrl
*/
private final HttpUrl baseUrl;
/**
* Response内容转换器
* 作用:负责把服务器返回的数据流(可能为字符串或二进制数据) 转化为R 类型的对象
*/
private final Converter<ResponseBody, R> responseConverter;
/*
* 网络请求的Http方法, 看这里就知道,一个网络访问必定含有httpMethod,所以一个ServiceMethod就会转换一个okhttp的Request网络请求,
* 一一对应。前面也提过,Retrofit的主线工作就是构建okhttp的Request请求
*/
private final String httpMethod;
private final String relativeUrl; // 网络请求的相对地址
private final Headers headers;// 网络请求的http请求头 键值对
private final MediaType contentType;// 网络请求的http报文body的类型
private final boolean hasBody;//是否含有body
private final boolean isFormEncoded;//表单是否encode
private final boolean isMultipart;//Multipart,多字段上传时使用
/**
* 方法参数处理器
* 作用:负责解析 ApiService 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;
* 下面会详细说明
*/
private final ParameterHandler<?>[] parameterHandlers;
// 说明:从上面的成员变量可以看出,ServiceMethod对象包含了访问网络的所有基本信息
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;
}
通过Builder构造模式来生成对象:
result = new ServiceMethod.Builder<>(this, method).build();
这里要用到注解的知识了JAVA反射_注解, 以及Java TypeJAVA反射_TYPE类型
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;
//前面的getNewsHot方法
this.method = method;
//获取方法的所有注解,返回一个数组,getNewsHot方法只有一个注解@GET("/")
this.methodAnnotations = method.getAnnotations();
//获取方法参数的参数化类型数组Type[] (注意与getParameterTypes的区别)。
//例如,如果有两个参数, 参数1是String类型, 参数2是List<String>,
//Type[0]就是java.lang.String, Type[1]就是java.util.List<java.lang.String>
this.parameterTypes = method.getGenericParameterTypes();
//getParameterAnnotations返回按参数顺序的二维数组,每个参数的对应一个一维注解数组,如果该参数没有注解,则该一维数组长度为零
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
callAdapter = createCallAdapter();
//responseType就是ResponseBody类型
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();
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);
}
createCallAdapter()方法:
private CallAdapter<T, R> createCallAdapter() {
//获取方法返回的泛型类型 Call<ResponseBody>
Type returnType = method.getGenericReturnType();
Log.d("kkunion", "ServiceMethod createCallAdapter returnType:"+returnType);
//hasUnresolvableType判断是否能处理该方法的返回类型, Utils工具类里面
//这里只说一下getActualTypeArguments方法,用于拿到Call<ResponseBody>中的ResponseBody,
// ResponseBody是一个实际的类,所以if (type instanceof Class<?>) {return false}, 流程继续往下走
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
//把Call<ResponseBody> returnType, @GET("/") annotations传进去
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对象,前面说过
③ 只需要知道callAdapterFactories这个list, 里面增加了一个对象就行了,这个对象实现了CallAdapter.Factory接口,做为默认的callAdapterFactory , 没继续往下读代码是看不懂它的作用的。
前面我们已经知道callAdapterFactories这个list,里面有一个对象了。这个对象干嘛用的,就是会传进去method的returnType,看该对象能不能处理。该对象是CallAdapter.Factory的子类,如果重写了public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit),并且不返回null,就表明该对象可以处理returnType。如果callAdapterFactories这个list里面有多个对象,则按顺序遍历看哪个可以处理。Retrofit.Builder里面就有一个方法可以往这个list添加对象,public Builder addCallAdapterFactory(CallAdapter.Factory factory) 。
这里list里面对象就是ExecutorCallAdapterFactory
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
//获取Call<ResponseBody>前面的Call, 即<>前面的类型
if (getRawType(returnType) != Call.class) {
//如果不是Call<T>形式的,返回null,表示处理不了该类型
return null;
}
//responseType就是ResponseBody类型
final Type responseType = Utils.getCallResponseType(returnType);
//重点: 这里返回了一个实现了CallAdapter<R, T>接口的对象SMO(简称), SMO里面有两个方法可以调用:
//一、Type responseType()
//二、Call<Object> adapt(Call<Object> call) , 这个方法接收一个实现了retrofit2.Call<T> extends Cloneable接口的对象RCO(简称),
//该方法返回一个实现了retrofit2.Call<T>接口的对象UCO(简称), 对UCO的操作, 就相当于对传进来RCO的操作
//UCO返回给用户使用,就是getNewsHot方法的返回值, 即对应了前面的代码: retrofit2.Call<ResponseBody> newsHot = service.getNewsHot();
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
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.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);
}
});
}
});
}
@Override public boolean isExecuted() {
return delegate.isExecuted();
}
@Override public Response<T> execute() throws IOException {
return delegate.execute();
}
@Override public void cancel() {
delegate.cancel();
}
@Override public boolean isCanceled() {
return delegate.isCanceled();
}
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}
@Override public Request request() {
return delegate.request();
}
}
}
那么谁来调用T adapt(Call<R> call) {}这个方法, 就是前面的invoked方法动态代理里面
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// 省略代码...
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
再回顾下前面的代码
retrofit2.Call<ResponseBody> hot = service.getNewsHot("1");
这样就能看出来了,hot对象其实就是UCO(简称), OkHttpCall<Object> okHttpCall就是RCO(简称),ExecutorCallbackCall就是SMO(简称)。对UCO的操作, 就是操作SMO, 间接操作RCO。 那么OkHttpCall是什么呢, 这里还不能进去看,因为OkHttpCall要用到ServiceMethod其他的方法,要先分析完
继续看回ServiceMethod类中的代码, 获取一个数据转换器
responseConverter = createResponseConverter();
Retrofit对象中,前面说过
④ 增加了一项默认数据转换器 BuiltInConverters, 而converterFactories在这里是空的,忽略它。
前面我们已经知道converterFactories这个list,里面有一个对象BuiltInConverters了。这个对象干嘛用的,就是会将Call<ResponseBody>中的ResponseBody作为Type给该对象,看该对象能不能处理该类型Type,。该对象是Converter.Factory的子类,如果重写了public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit),并且不返回null,就表明该对象可以处理类型Type。如果converterFactories这个list里面有多个对象,则按顺序遍历看哪个可以处理。Retrofit.Builder里面就有一个方法可以往这个list添加对象,public Builder addConverterFactory(Converter.Factory factory) 。
这里list里面对象就是BuiltInConverters
final class BuiltInConverters extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
//从网络返回数据时, 表明可以处理ResponseBody这种格式
//实际需要转换时,就会调用该对象的T convert(F value) throws IOException方法
//参看BufferingResponseBodyConverter
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
return null;
}
//发送数据到网络前, 是否对RequestBody数据做另外的处理
//RequestBodyConverter没有做处理,直接发送RequestBody
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}
// 处理Call<Void>这种格式
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();
@Override public Void convert(ResponseBody value) {
value.close();
return null;
}
}
// 没有做处理,直接发送RequestBody
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
@Override public RequestBody convert(RequestBody value) {
return value;
}
}
// 处理声明了Streaming注解的格式
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) {
return value;
}
}
//处理Call<ResponseBody>这种格式
static final class BufferingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final BufferingResponseBodyConverter INSTANCE = new BufferingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) throws IOException {
try {
// Buffer the entire body to avoid future I/O.
return Utils.buffer(value);
} finally {
value.close();
}
}
}
static final class ToStringConverter implements Converter<Object, String> {
static final ToStringConverter INSTANCE = new ToStringConverter();
@Override public String convert(Object value) {
return value.toString();
}
}
}
继续看回ServiceMethod类中的代码, 下面主要是用来获取注解中的信息, 代码很长很长,是个苦力活
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);
注解分析完成后,最后会得到这些信息:
httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart
ServiceMothod中还有一个方法toCall, 就是根据httpMothod, baseUrl, relativeUrl…等信息,去构建出一个okhttp3.Call来返回:
/** Builds an HTTP request from method arguments. */
okhttp3.Call toCall(@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 callFactory.newCall(requestBuilder.build());
}
那么构建出来的okhttp3.Call是给谁使用的呢, 给OkHttpCall这个类使用。我们已经知道OkHttpCall是动态代理对象,它能干的活就是Call<T>中定义的接口:
public interface Call<T> extends Cloneable {
Response<T> execute() throws IOException;
void enqueue(Callback<T> callback);
boolean isExecuted();
void cancel();
boolean isCanceled();
Call<T> clone();
Request request();
}
先来看void enqueue(Callback callback);
@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 {
// 调用ServiceMethod的方法toCall, 构建一个okhttp3.Call
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 {
// 从okhttp3.Response转换成retrofit2.Response
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();
}
}
});
}
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = serviceMethod.toCall(args);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// 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) {
rawBody.close();
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//这里就用到了前面分析的数据转换器BuiltInConverters
T body = serviceMethod.toResponse(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;
}
}
看到这里,我们已经拿到网络数据,并转换成我们所需要的格式了,流程基本结束了。