一,前言
Retrofit其实是将OKhttp封装起来,和volley一样。那解析Retrofit其实就是解析它如何封装使用OKhttp,那我直接从其使用上来跟踪源码。
总体上可以分为四步:
- 创建Retrofit对象
- 通过Retrofit获取接口对象
- 通过接口对象获取请求服务的Call对象
- 最后通过Call的异步enqueue或同步execute来执行网络请求并回调结果。
下面也是通过这四步来解析源码
二,创建Retrofit对象
先占时不考虑RxJava的使用
Retrofit retrofit = new Retrofit.Builder() //1
.baseUrl(baseUrl) //2
.addConverterFactory(GsonConverterFactory.create()) //3
.build(); //4
Retrofit是通过建造者模式来构建对象的,那很明显,这里只是配置了请求网络的参数而已,而这些配置在后面的网络请求和结果转换用到了。
第二步是为了配置请求服务的地址;第三部是配置返回结果的转换器,使结果为对象。
2.1 Builder()
public static final class Builder {
private final Platform platform;
// 网络请求器的工厂
private @Nullable okhttp3.Call.Factory callFactory;
// 网络请求的url地址
private HttpUrl baseUrl;
// 数据转换器工厂的集合,生产数据转换器(converter)
private final List converterFactories = new ArrayList<>();
// 网络请求适配器工厂的集合,生产网络请求适配器(CallAdapter)
private final List adapterFactories = new ArrayList<>();
//// 请求结束后回调方法的执行Executor
private @Nullable Executor callbackExecutor;
// 是否提前对业务接口中的注解进行验证转换的标志位
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
// 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());
}
public Builder() {
this(Platform.get());
}
...
}
Builder里存储的参数都会在Retrofit创建时赋值给它,后面的build()再介绍。
在创建Builder()对象时,其实只赋值了两个属性:platform 和converterFactories。可以知道默认的请求结果转换器为BuiltInConverters,我们开发中一般使用GsonConverterFactory.create()。
2.1.1 Platform
Platform是单例模式,通过Platform.get()来获取对象。
class Platform {
//单例对象是通过findPlatform()创建的
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
//如果是安卓系统,就返回Android()
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
// Java8()
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
static class Android extends Platform {
//请求结果回调使用的Executor,如果Builder没有赋值给callbackExecutor,就会调用这个方法赋值
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//Builder里的CallAdapter.Factory,最后会在build()里赋值给adapterFactories,作为默认的网络请求适配器
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
//那可以看出默认的网络适配器是ExecutorCallAdapterFactory实现的
return new ExecutorCallAdapterFactory(callbackExecutor);
}
//调用handler使回调在主线程执行
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
}
最为安卓平台,Platform最终赋值的对象是静态内部类Android,这个对象作为默认配置,会在Builder的build()方法中调用赋值。
defaultCallbackExecutor是返回回调执行的Executor,返回的MainThreadExecutor是使用handler让回调操作在主线程执行。如果在Builder中没有指定回调的Executor,会调用defaultCallbackExecutor指定异步网络请求的回调在主线程执行。
defaultCallAdapterFactory则是指定默认网络适配器工厂为ExecutorCallAdapterFactory,调用接口方法返回的Call,就是这个类创建的。具体等后面使用其功能再介绍。
2.2 其它配置
2.2.1 baseUrl
就是将String类型的url,经过合格性检测,拆分存储,再转换成HttpUrl赋值给baseUrl。
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
//将String的转为HttpUrl
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List pathSegments = baseUrl.pathSegments();
//如果路径结尾不是以"/"结尾,会抛出异常
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
值得注意的是,路径必须以"/"结尾
2.2.2 addConverterFactory
//将转换工厂保存到converterFactories中,在构造器中,已经add了一个BuiltInConverters
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
上面的例子是添加GsonConverterFactory,下面来看看它是如何转换的。
2.2.2.1 GsonConverterFactory
public final class GsonConverterFactory extends Converter.Factory {
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter> adapter = gson.getAdapter(TypeToken.get(type));
//返回对应的Converter对象
return new GsonResponseBodyConverter<>(gson, adapter);
}
}
final class GsonRequestBodyConverter implements Converter {
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
//将ResponseBody转为泛型对象
return adapter.read(jsonReader);
} finally {
value.close();
}
}
通过convert转换的类型,是在调用responseBodyConverter创建对象时传入的请求接口的返回类的泛型。也就是例子中的HttpResult。
如果要自定义Converter来实现请求结果转化,按上面那样就可以了,使用工厂方法模式。
- 继承Converter,在convert方法中返回转换后的结果,比如GsonRequestBodyConverter中是把ResponseBody转成自己需要转的类型。
- 继承Converter.Factory,在responseBodyConverter中将相应的Converter对象返回。
- 在Retrofit的创造器中调用addConverterFactory添加相应的Converter.Factory。
2.3 build()
这部将根据先前的配置生成Retrofit,其实Builder中的配置属性几乎都赋值给了Retrofit。
public Retrofit build() {
//callFactory是类okhttp3.Call.Factory的对象,如果自己没有设置了OkHttp对象,则会自己创建一个。
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//回调方法执行器
Executor callbackExecutor = this.callbackExecutor;
//没有指定的话,就用构造器中赋值的platform中的,也就是将回调放在主线程
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 将配置的网络适配器进行保护性拷贝
List adapterFactories = new ArrayList<>(this.adapterFactories);
//添加默认的网络适配器,也就是ExecutorCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 与网络适配器的排序不同,默认的BuiltInConverters放在第一位,后面才是添加的
List converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
对于网络适配器队列存储顺序和数据转化器的队列顺序不同,其实是在后面给ServiceMethod赋值相应属性时,采取了不同的取值策略。网络适配器优先获取队列前面的;数据转化器虽然也是从队列前面开始适配,但默认的BuiltInConverters要接口返回类型为ResponseBody或Void才会返回Converter对象,返回类型为其它时,会继续遍历后面的数据转化器,所以在设定返回值为对象时,GsonConverterFactory会起作用。具体后面ServiceMethod创建时会介绍。
2.4 总结
在最后build()中,可以发现创建Retrofit时,传入了6个参数。
- OKHttp对象。比如设置连接超时时间的OKHttp
- 服务器地址。必填
- 请求结果的数据转换器。对于请求结果的返回类型进行转换
- 网络适配器。默认为ExecutorCallAdapterFactory,通常设置为RxJava2CallAdapterFactory.create()。
- 回调方法执行器。默认回调在主线程执行。
- 是否提前对业务接口中的注解进行验证转换的标志位。在create中有用到。
比较重要的类有设置默认回调方法执行器和默认网络适配器的Platform;默认的数据转换器BuiltInConverters。
三 通过Retrofit获取接口对象
MovieService movieService = retrofit.create(MovieService.class);
public interface MovieService {
//get请求
@GET("top250")
//网络请求数据的方法,@Query配置请求参数
Call>> getTopMovie(@Query("start")int start, @Query("count")int count);
}
MovieService是个接口,里面定义了一个方法,通过注解上面配置了请求接口的参数配置,retrofit通过方法的参数创建接口对象。
那来看看如何通过接口来获取对象。
3.1 create
public T create(final Class service) {
Utils.validateServiceInterface(service);
//是否提前通过注解加验证加载请求接口,会将接口中的方法都解析成ServiceMethod,并加入serviceMethodCache缓存中
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//创建动态代理对象,用来代理接口
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[] { service },
new InvocationHandler() { //将代理类的实现交给 InvocationHandler类作为具体的实现
private final Platform platform = Platform.get();
//被代理执行的方法,是通过在InvocationHandler中的invoke方法调用的
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// Object的方法直接调用原方法
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//android默认为false,不走
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//这里才是被代理方法真正执行的地方
//通过接口方法的注解来获取ServiceMethod
ServiceMethod
代理模式的动态代理是实现接口方法调用的关键,动态代理也只能代理接口,invoke方法是接口方法正在实现的地方,生成的代理对象在运行时存在内存中。
这样
那接下来看接口方法的调用。
四 通过接口对象获取请求服务的Call对象
Call>> call = movieService.getTopMovie(0, 10);
这里的getTopMovie方法调用,是在上面invoke方法中实现的,主要是这几行代码
//通过方法注解配置,获取ServiceMethod
ServiceMethod serviceMethod =
(ServiceMethod) loadServiceMethod(method);
//根据ServiceMethod创建OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
//创建Call
return serviceMethod.callAdapter.adapt(okHttpCall);
4.1 loadServiceMethod
ServiceMethod, ?> loadServiceMethod(Method method) {
//从缓存中获取,如果先前创建过久直接用
//create中的eagerlyValidateMethods方法会提前创建对象并缓存
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;
}
对象的创建是通过new ServiceMethod.Builder<>(this, method).build()实现的。
4.1.1 new ServiceMethod.Builder<>(this, method)
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//获取方法里的注解
this.methodAnnotations = method.getAnnotations();
//获取方法的参数类型
this.parameterTypes = method.getGenericParameterTypes();
//获取方法参数里的注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
就是赋值。
4.1.2 build()
public ServiceMethod build() {
//1.根据接口的返回类型和注解,从retrofit中获取网络适配器
callAdapter = createCallAdapter();
//方法返回值泛型的类型,也就是网络请求的返回值类型
responseType = callAdapter.responseType();
//2.根据方法的返回类型和注解,网络数据转换器
responseConverter = createResponseConverter();
//3.获取方法上的注解
for (Annotation annotation : methodAnnotations) {
//根据注解获取配置
parseMethodAnnotation(annotation);
}
//4.获取方法参数里的注解
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);
}
return new ServiceMethod<>(this);
}
重点关注下网络适配器和数据转换器是如何获得的,根据前面的Builder可知,retrofit里它们都是以数组保存的,那获取规则又如何呢。
4.1.2.1 createCallAdapter
先看网络适配器如何获取的。
private CallAdapter createCallAdapter() {
//返回值类型
Type returnType = method.getGenericReturnType();
//方法注解
Annotation[] annotations = method.getAnnotations();
try {
//通过retrofit的callAdapter方法返回的
return (CallAdapter) 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);
}
}
public CallAdapter, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
//从0开始
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
//在分析的例子中,没有配置网络适配器,所以用的默认的ExecutorCallAdapterFactory
//使用RxJava会配置了RxJava2CallAdapterFactory
CallAdapter, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
}
因为例子没有配置网络适配器
这里是使用默认的网络适配器ExecutorCallAdapterFactory,如果配置了RxJava2CallAdapterFactory,它会在默认网络适配器的前面,那时就会使用RxJava2CallAdapterFactory了。ExecutorCallAdapterFactory这个到后面通过网络适配器返回的Call调用enqueue时再介绍。
4.1.2.2 createResponseConverter
解析的例子中,是配置了GsonConverterFactory数据转换器。和上面的网络适配器一样,数据转换器也是从retrofit保存的配置信息中获取的
public Converter nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
//从0开始
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
//默认的数据转换器BuiltInConverters,如果接口方法返回值类型不是ResponseBody和Void的话,返回null
//分析的这个例子中,接口方法返回值的泛型是HttpResult,所以会循环到下个GsonConverterFactor对象
Converter converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter) converter;
}
}
}
数据转换器把默认的BuiltInConverters放在了第一位,但还是根据接口方法返回值泛型会过滤选择。所以在自定义转换器时,要过滤要转换的类型。
4.2 ExecutorCallAdapterFactory
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
serviceMethod.callAdapter.adapt(okHttpCall)
又回到Retrofit中create的动态代理中来,到invoke中最后一步,返回Call。(如果是RxJava,则返回Observable)
根据上面的分析,可以知道serviceMethod.callAdapter对象是默认的ExecutorCallAdapterFactory。callAdapter和Converter都采用了工厂方法模式来实现,理解这个更有助于自定义它们。
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才行
if (getRawType(returnType) != Call.class) {
return null;
}
//返回值泛型的类型,如例子中的HttpResult
final Type responseType = Utils.getCallResponseType(returnType);
//返回CallAdapter
return new CallAdapter>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call adapt(Call call) {
//相应的call对象
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
}
CallAdapter和它的工厂CallAdapter.Factory,是自定义CallAdapter的关键。
- CallAdapter的adapt方法返回接口方法的返回值,上面是返回Call对象。如果是RxJava,则返回Observable对象。
- CallAdapter.Factory则是创建CallAdapter的工厂,它的get方法返回CallAdapter对象
- CallAdapter的adapt方法的返回对象,是实现后续网络请求的关键,自定义要在返回对象中将自己封装的网络请求放在里面。
4.3 总结
到这里,如何通过接口对象调用方法获取Call已经很明了了。就是通过动态代理对象里的InvocationHandler里的invoke方法实现,调用接口对象方法实际上是调用invoke方法。
在invoke中,首先根据接口方法的注解和Retrofit里的配置通过建造者模式生成ServiceMethod对象,再生成实现网络请求的对象OkHttpCall,通过ServiceMethod中的CallAdapter来生成封装了OkHttpCall的Call对象(RxJava则是Observable)。
自定义CallAdapter的关键是实现CallAdapter和CallAdapter.Factory。
五 请求网络
请求网络时通过调用call.enqueue,那来看看默认的Call对象相应方法的实现,也就是ExecutorCallAdapterFactory里的ExecutorCallbackCall
static final class ExecutorCallbackCall implements Call {
//回调方法执行器
final Executor callbackExecutor;
//OkHttpCall对象,是生成ExecutorCallbackCall时传入的
final Call delegate;
//在CallAdapter的adapt方法中被创建赋值
ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}
@Override public void enqueue(final Callback callback) {
checkNotNull(callback, "callback == null");
//代理模式,最终还是OkHttpCall实现
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
//回调执行器执行回调
callbackExecutor.execute(new Runnable() {
@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 call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
//失败回调
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}
}
ExecutorCallbackCall用的代理模式,最终实现的对象的OkHttpCall。
OkHttp的使用就分四步
- 创建okHttpClient对象
- 创建一个Request
- new call
- 请求加入调度
真正实现网络请求的就是OKHttp,我们可以从上面四步了解网络请求的实现。第一步在创建retrofit对象时就已经完成了。
5.1 OkHttpCall
OkHttpCall是retrofit2中封装的一个类,内部调用还是通过ServiceMethod获取网络请求配置并生成okhttp3.Call来实现。
@Override public void enqueue(final Callback callback) {
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.生成okhttp3.Call对象,默认是OkHttpClient的newCall创建,为RealCall对象
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}
//2.发送异步网络请求
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response response;
try {
//3.通过存在serviceMethod的Converter转换数据类型
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
//4.回调接口
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 response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
可以看出实现网络请求的是OKhttp,那只要关注okhttp3.Call是如何创建和网络请求结果如何转换就好了。
5.1.1 createRawCall()
okhttp3.Call的创建就完成了OkHttp使用的前三步了,下面来看看前三部是怎么实现的吧。
所有的网络配置信息都在ServiceMethod中,很明显,它们的生成也都在ServiceMethod中,通过默认的OkHttpClient的newCall创建,为RealCall对象,这些还是后面看OKHttp的解析了解吧。
private okhttp3.Call createRawCall() throws IOException {
//创建Request对象,将请求网络的信息都封装在里面
Request request = serviceMethod.toRequest(args);
//callFactory是okhttp3.Call.Factory,在创建Retrofit时默认的OkHttpClient
//正常OKhttp生成Call的流程
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
创建Request,再创建okhttp3.Call,这是正常的OkHttp请求的第二三步。这里只关心Retrofit的封装,就看toRequest方法了。
5.1.1.1 serviceMethod.toRequest
Request toRequest(@Nullable Object... args) throws IOException {
//创造者模式构建对象
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
//接口方法的参数的注解结合
ParameterHandler[] handlers = (ParameterHandler[]) 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 + ")");
}
//对接口方法参数,会在apply中转换参数类型,并添加到requestBuilder中。
//数据转换默认使用BuiltInConverters.ToStringConverter.INSTANCE,也就是直接将参数值toString()
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
//里面通过参数,用普通的OKhttp的建造器生成Request
return requestBuilder.build();
}
//例子中,添加的请求参数是Query,所以上面handlers[p].apply的实现是
static final class Query extends ParameterHandler {
@Override void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) return; // Skip null values.
//这里就是把value.toString()了
String queryValue = valueConverter.convert(value);
if (queryValue == null) return; // Skip converted but null values
//添加到请求url里去
builder.addQueryParam(name, queryValue, encoded);
}
}
对于接口方法注解的解析,我就不做太多介绍了。handlers[p].apply是将方法参数的配置信息添加到requestBuilder中去,将参数配置都添加后,在build中,用OKhttp的Request.Builder生成Request对象。
RequestBuilder将baseUrl和请求接口方法里的注解配置信息组合起来,将配置信息添加入Request.Builder中,创建Request。
5.2 parseResponse
call.enqueue这个方法是okhttp3.Call的方法,就不分析了,主要分析请求服务结束后,将数据类型转换为回调接口需要的类型。
Response parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();
// 移除Response中的响应正文,在此基础上创建一个新的Response
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 {
//调用数据转换器进行类型转换
T body = serviceMethod.toResponse(catchingBody);
//将转换后内容和空body的Response再组合成Retrofit里的Response
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;
}
}
这里将okhttp3.Response,将响应正文通过数据转换器转换,再和空响应正文的okhttp3.Response组合成Retrofit里的Response,用于回调使用。
callback.onResponse是回调了默认网络适配器里的ExecutorCallbackCall里的Callback,然后ExecutorCallbackCall里再使用默认的Executor在主线程回调例子里的Callback。
六 总结
- Converter和CallAdapter都是用工厂方法模式实现的,自定义时要分别实现产品类和工厂类,在工厂类中创建产品。
- Retrofit是通过建造者模式创建的,Retrofit.Builder()主要配置:网络请求工厂(okhttp3.Call.Factory),网络请求地址(HttpUrl),数据转换器(List
),网络适配器(List ),回调执行方法(Executor),是否提前对业务接口中的注解进行验证转换的标志位(validateEagerly) - 接口方法里通过注解配置了网络请求的配置,通过Retrofit的create方法,动态代理实现了接口方法。接口方法的返回值是网络适配器返回对象,类型要和接口方法的返回值一致。
- 动态代理的invoke方法里,通过Retrofit的配置和接口方法的注解配置生成ServiceMethod对象,这个对象保存了网络请求的所有配置。大部分方法和解析注解生成配置有关,主要关注两个方法:一个toRequest通过RequestBuilder生成OKhttp的Request,toResponse可以利用数据转换器将ResponseBody转为请求接口方法返回值泛型。这两个方法都是给OkHttpCall使用。
- 再通过ServiceMethod创建了OkHttpCall,里面有请求网络的方法,实际上是根据ServiceMethod的配置网络信息生成的Request再生成okhttp3.Call,将请求结果通过ServiceMethod的配置转换器进行数据转换,最终回调给调用它的类(默认ExecutorCallbackCall)。
- ExecutorCallAdapterFactory是默认的网络适配器工厂,在动态代理的invoke方法里,创建ServiceMethod时用get方法生成适配器后,再通过适配器的adapt生成ExecutorCallbackCall返回值,ExecutorCallbackCall中用静态代理模式实现,被代理对象是OkHttpCall。
- GsonConverterFactory的具体转换结果类型,是在创建ServiceMethod时,用解析的接口方法中的返回值泛型确定的。
- 随后再列下关键的几个类:
- Retrofit:用创建者模式存储网络配置。
- ServiceMethod:通过接口方法注解的配置和Retrofit里的配置,生成ServiceMethod。toReques和toResponse方法供给OkHttpCall使用。
- ServiceMethod中利用RequestBuilder,生成Request请求。Request利用Retrofit配置的网络参数,和ServiceMethod里解析接口方法里的注解配置,生成Request请。
- OkHttpCall:网络请求的封装类,内部结合ServiceMethod的toReques生成OKHttp实现网络请求,再用ServiceMethod的toResponse转换结果回调给调用它的对象,这个对象是网络适配器adapt生成。
参考
Android OkHttp完全解析 是时候来了解OkHttp了
你真的会用Retrofit2吗?Retrofit2完全教程
Android:手把手带你 深入读懂 Retrofit 2.0 源码