Retrofit
是Android
应用层最为广泛的网络请求框架之一。
它通过动态代理、工厂模式、Builder
模式等设计模式,对Okhttp
进行了巧妙封装。
本文,将对Retrofit2
源码进行分析。若无特殊说明,源码api为2.7.2
在使用Retrofit
时,我们先定义一个接口,然后通过调用retrofit.create
方法,得到一个接口的实例,最后通过该实例执行我们的操作。
Retrofit
在设计过程中,有一个很重要的知识点,动态代理.
在正式学习Retrofit
源码之前,先对Java
中的动态代理进行了解。
先定义一个接口:
代码片1
public interface ITest {
@GET("/test")
public void add(int a, int b);
}
通过动态代码的代码如下:
代码片2
ITest iTest = (ITest) Proxy.newProxyInstance(ITest.class.getClassLoader(),
new Class<?>[]{
ITest.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Integer a = (Integer) args[0];
Integer b = (Integer) args[1];
System.out.println("方法名:" + method.getName());
System.out.println("参数:" + a + " , " + b);
GET get = method.getAnnotation(GET.class);
System.out.println("注解:" + get.value());
return null;
}
});
iTest.add(3, 5);
输出结果如下:
I/System.out: 方法名:add
I/System.out: 参数:3 , 5
I/System.out: 注解:/test
可以看到通过 Proxy.newProxyInstance
产生的代理类,当调用接口的任何方法时,都会调用 Proxy#InvocationHandler
方法,在这个方法中可以拿到传入的参数、注解等。
代码片3
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.addConverterFactory(GsonConverterFactory.create(mGson))
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> call = service.listRepos("gaolhjy");
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
Log.e(TAG, "onResponse: " + "success");
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
Log.e(TAG, "onResponse: " + "onFailure");
}
});
上述代码,是比较典型的使用Retrofit进行的网络请求的写法。
代码片4
Retrofit retrofit = new Retrofit.Builder() //1.创建builder
.baseUrl("https://api.github.com/") //2.配置builder
.build(); //3、创建Retrofit实例
代码片5
public static final class Builder {
private final Platform platform; //运行Retrofit的平台
//省略部分代码
//根据Platform构造
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
//根据另外一个Retrofit构造
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
//省略部分代码
}
和okhttp
一样,Retrofit
的实例化也是采用builder
模式。
我们使用了无参的构造函数来创建Builder
,Builder
的无参构造函数首先通过Platform.get()
获取了一个Platform
实例赋值给了platform
字段,前面提到过Retrofit
是有Platform
的概念,Retrofit
支持java
和Android
平台。
我们来看一下Platform
类.
代码片6
class Platform {
//单例
private static final Platform PLATFORM = findPlatform();
//返回Platform 对象
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
//android.os.Build这个类是Android独有的
//这里要求JVM查找并加载Build.class对象
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
//如果是Android平台,创建一个Android实例返回,Android继承自Platform
return new Android();
}
} catch (ClassNotFoundException ignored) {
//找不到android.os.Build,会抛出异常,捕捉,继续执行
}
//返回默认Platform实例,并传hasJava8Types为true
return new Platform(true);
}
private final boolean hasJava8Types;
Platform(boolean hasJava8Types) {
this.hasJava8Types = hasJava8Types;
}
//返回默认的线程切换执行器
@Nullable Executor defaultCallbackExecutor() {
return null;
}
//返回默认的网络请求适配器工厂
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
return hasJava8Types
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
int defaultCallAdapterFactoriesSize() {
return hasJava8Types ? 2 : 1;
}
List<? extends Converter.Factory> defaultConverterFactories() {
return hasJava8Types
? singletonList(OptionalConverterFactory.INSTANCE)
: emptyList();
}
int defaultConverterFactoriesSize() {
return hasJava8Types ? 1 : 0;
}
boolean isDefaultMethod(Method method) {
return hasJava8Types && method.isDefault();
}
@Nullable Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
@Nullable Object... args) throws Throwable {
// Because the service interface might not be public, we need to use a MethodHandle lookup
// that ignores the visibility of the declaringClass.
Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
constructor.setAccessible(true);
return constructor.newInstance(declaringClass, -1 /* trusted */)
.unreflectSpecial(method, declaringClass)
.bindTo(object)
.invokeWithArguments(args);
}
static final class Android extends Platform {
Android() {
super(Build.VERSION.SDK_INT >= 24);
}
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//线程切换执行器
// MainThreadExecutor,它是一个Executor,它的execute方法的实现就是简单通过Handler把任务Runnable切换回主线程执行,就是说,线程池会把每一个线程提交的任务都切回主线程执行
static class MainThreadExecutor implements Executor {
// 构造Handler时通过Looper.getMainLooper()来构造
// 所以Handler的消息都会执行在主线程
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
}
Retrofit.class
public static final class Builder {
private final Platform platform; //Retrofit运行的平台
private @Nullable okhttp3.Call.Factory callFactory; //网络请求执行器工厂,用创建网络请求执行器实例,来自okhttp, 不是Retrofit中的那个Call
private @Nullable HttpUrl baseUrl; //网络请求的Url地址
private final List<Converter.Factory> converterFactories = new ArrayList<>(); //数据转化器工厂列表
private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(); //网络请求工厂列表
private @Nullable Executor callbackExecutor; //线程切换执行器
private boolean validateEagerly; //标志位,是否提前对serviceMethod进行缓存(在创建Api接口实例会讲到)
....
//省略创建builder的代码
//我们传入的String类型的Url,最终还是会解析成HttpUrl类型,它是Retrofit中url的代表
public Builder baseUrl(URL baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl.toString()));
}
public Builder baseUrl(String baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
public Builder baseUrl(HttpUrl baseUrl) {
Objects.requireNonNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
// baseUrl最后一定要接一个
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
//把converFactory添加到数据转化器工厂列表中
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(Objects.requireNonNull(factory, "factory == null")); //converterFactories是一个ArrayList集合
return this;
}
//把CallAdapterFactory添加到网络请求适配器工厂列表中
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
//从service方法返回Call时,在其上调用Callback方法的执行程序。
//注意:executor不用于addCallAdapterFactory自定义方法返回类型
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = Objects.requireNonNull(executor, "executor == null");
return this;
}
//获取网络请求适配器工厂列表
public List<CallAdapter.Factory> callAdapterFactories() {
return this.callAdapterFactories;
}
//获取数据转化器工厂列表
public List<Converter.Factory> converterFactories() {
return this.converterFactories;
}
//修改validateEagerly标志位
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
//省略代码. 第三部分 创建Retrofit实例 会讲解
}
Builder
中所有的字段都贴出来了,方法只贴了几个常用的出来,我们调用Builder
的相应方法,就是在为Builder
的相应字段赋值,很简单。这也是Builder
模式的优势。
其中需要注意的是,当我们添加ConverterFactory
或CallAdapterFactory
时,它们都是添加到各自的列表中,这也说明Retrofit
添加Converter
和CallAdapter
是可以同时存在多个的.这是为什么呢?这是因为Retrofit允许为Api接口里面定义的每一个方法都定义对应的Converter
和CallAdapter
,每当我们调用Api的某个接口方法时,Retrofit
都会遍历网络请求适配器工厂列表callAdapterFactories
,把方法的返回值returnType
和注解信息annotations
传进每个Factory
的get
方法中,看某个Factory
是否愿意处理这个方法,为这个方法创建对应CallAdapter
实例;同理,当Retrofit
解析某个Api
接口方法的网络请求数据时,它同样会遍历数据转化器工厂列表converterFactories
,把方法的相关信息传给Factory
的responseBodyConverter
或requestBodyConverter
方法,看某个Factory
是否愿意处理这个方法,为这个方法创建对应ResponseBodyBodyConverter
或RequestBodyConverter
实例,这两个过程在待会的源码分析都会体现到。
Retrofit.class
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//配置网络请求执行器工厂callFactory
okhttp3.Call.Factory callFactory = this.callFactory;
//如果没有指定,使用默认的
if (callFactory == null) {
//默认指定为OkHttpClient, OkHttpClient实现了Call.Factory接口,OkHttpClient和Call都是来自okhttp的
callFactory = new OkHttpClient();
}
//配置线程切换执行器callbackExecutor
Executor callbackExecutor = this.callbackExecutor;
//如果没有指定,使用默认的
if (callbackExecutor == null) {
//默认指定为运行平台默认的线程切换执行器
//在Android中,defaultCallbackExecutor方法的返回值就是MainThreadExecutor实例
callbackExecutor = platform.defaultCallbackExecutor();
}
//配置网络请求适配器工厂列表
//添加用户指定的网络请求适配器工厂列表
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//添加运行平台默认的网络请适配器工厂到列表中
//在Android中,defaultCallAdapterFactory方法返回值就是ExecutorCallAdapterFactory实例,并把MainThreadExecutor实例传进方法,所以ExecutorCallAdapterFactory持有MainThreadExecutor实例(回去看构造Builder阶段)
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
//配置数据转化器工厂列表
List<Converter.Factory> converterFactories =
new ArrayList<>(1 + this.converterFactories.size());
//添加Retrofit默认的数据转化器工厂BuiltInConverters
converterFactories.add(new BuiltInConverters());
//添加用户指定的数据转化器工厂列表
converterFactories.addAll(this.converterFactories);
//创建一个Retrofit实例返回,并把上面的配置好的字段传进构造
//这些字段和Retrofit中相应的字段同名,unmodifiableList就是创建一个不可修改的列表
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
build
方法中把没有在配置Builder
阶段中赋值的字段指定了默认值,然后把网络请求Url地址baseUrl、网络请求执行器工厂callFactory
、线程切换执行器callbackExecutor
、网络请求适配器工厂列表callAdapterFactories
、数据转化器工厂列表converterFactories
、标志位validateEagerly
这六件套传进了Retrofit
的构造,创建一个Retrofit实例返回。
其中要注意的是,按照添加顺序,工厂列表的优先级为:用户指定的网络请适配器工厂列表 > 运行平台默认的网络请求适配器工厂;Retrofit
默认的数据转化器工厂 > 用户指定的数据转化器工厂列表。在遍历这些列表时是从前往后遍历的,越靠前的越先被访问。
通过创建builder
、配置builder
、创建Retrofit
这三步后,指定了Retrofit
的运行平台、配置好了Retrofit
网络请求Url
地址、网络请求执行器工厂、线程切换执行器、网络请求适配器工厂列表、数据转化器工厂列表等字段,并创建了一个Retrofit
实例。
GitHubService service = retrofit.create(GitHubService.class);
Retrofit
的create
方法如下:
Retrofit.class
代码片8
// 泛型T就是GithubService接口
public <T> T create(final Class<T> service) {
validateServiceInterface(service); //验证服务接口
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] {
service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable 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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs); //重点分析1
}
});
}
整体结构为 Proxy.newProxyInstance
即动态代理。 关于动态代理的知识,在 一.动态代理 中已经学习。
上述代码整体上看,就是传入什么类(比如GitHubService.class
),经过动态代理之后,返回 GitHubService.class
.
当我们调用Retrofit
的create
方法后,它返回了一个代理对象实例。
这个代理对象实现了create
方法传进去的接口,接下来当我们调用Api接口方法时,就是在调用代理对象的同名方法,这个方法的处理逻辑就会委托给InvocationHandler
实例的invoke方法执行。使用了动态代理之后的好处是:我们可以把网络请求的参数都集中在invoke方法中处理,而不需要为某一个接口定义一个实现类,这样降低了实现的难度。
代码片9
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
ServiceMethod<?> loadServiceMethod(Method method) {
//从serviceMethodCache根据方法method获取ServiceMethod
ServiceMethod<?> result = serviceMethodCache.get(method);
//如果获取得到就直接返回
if (result != null) return result;
//如果获取不到就为这个method创建一个ServiceMethod
//上锁,所以创建的ServiceMethod是一个单例
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//为method创建一个ServiceMethod
result = ServiceMethod.parseAnnotations(this, method); //parseAnnotations的中文意思是解析注解(重点分析2)
//然后以方法method为键,ServiceMethod为值,放入serviceMethodCache(map集合)缓存起来
serviceMethodCache.put(method, result);
}
}
return result;
}
代码片10
call.enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) {
Log.e(TAG, "onResponse: " + "success");
}
@Override
public void onFailure(Call<List<Repo>> call, Throwable t) {
Log.e(TAG, "onResponse: " + "onFailure");
}
});
异步请求需要把结果通过Callback
回调给上层.
call
是一个接口, 它的实现类通过搜索后发现有且只有2个:
OkHttpCall.class
final class OkHttpCall<T> implements Call<T>
DefaultCallAdapterFactory#ExecutorCallbackCall
static final class ExecutorCallbackCall<T> implements Call<T> {
到底是哪一个呢?思路陷入了僵局。
我们回过头看代码片8第12行代码 loadServiceMethod(method).invoke
,看看调用invoke
方法是怎么样的.
代码如下:
代码片11
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
//省略部分代码
....
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
这是一个抽象方法, ServiceMethod
返回值为 HttpServiceMethod.parseAnnotations
点 HttpServiceMethod.parseAnnotations
源码进去看,
代码片12
HttpServiceMethod<ResponseT, ReturnT> parseAnnotations
结合代码片8、代码片11、代码片12, 综合看:
loadServiceMethod(method).invoke
其实转移到了HttpServiceMethod
类的invoke
方法了.
那我们点进去看一下:
HttpServiceMethod.class
代码片13
@Override final @Nullable ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
在这里,果然看到了Call
的实现类. 即OkhttpCall
.
也就是说代码片10中的 call.enqueue
实际上调用的是OkhttpCall
的enqueue
方法.
代码片14
@Override public void enqueue(final Callback<T> callback) {
Objects.requireNonNull(callback, "callback == null");
//来自Okhttp的Call
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 {
//第一次发起网络请求,创建Okhttp的Call
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
}
if (failure != null) {
//通过callback把错误回调出去
callback.onFailure(this, failure);
return;
}
if (canceled) {
call.cancel();
}
//调用Okhttp的Call的enqueue方法发起异步请求
//传入的是Okhttp的Callback
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
//调用parseResponse方法把Okhttp的Response解析成Retrofit的Response
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
//通过callback把结果回调出去
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
//Okhttp的错误回调
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
//通过callback把错误回调出去
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
throwIfFatal(t);
t.printStackTrace(); // TODO this is not great
}
}
});
}
OkhttpCall
的enqueue
方法大体分为3步:
Okhttp
的Call
实例,赋值给临时变量call
:createRawCall
方法就创建来自Okhttp
的Call
,赋值给临时变量call
和成员变量rawCall
;rawCall
实例赋值给临时变量call
。Okhttp
的Call
的enqueue
方法发起异步请求;parseResponse
方法把Okhttp
的Response
解析成Retrofit
的Response
。以异步为例,Retrofit
通过ExecutorCallbackCall
的enqueue
发起的网络请求,最终会通过OKhttpCall
的enqueue
方法来发起网络请求.
OkhttpCall
的enqueue
方法中,首先会调用创建一个来自Okhttp
的Call
实例,然后通过这个Okhttp
的Call
实例的enqueue
方法来发起异步请求,当网络请求结果Okhttp
的Response
返回时,调用parseResponse
方法解析Response
,parseResponse
方法里面还会调用ServiceMethod
的toResponse
方法通过Converter
实例的converter
方法把ResponseBody
转化为我们想要的数据。不同的数据转化有不同的实现,在Retrofit的默认实现中,它就是直接返回Okhttp
的ResponseBody
,最后把这个转化后的body
和原始的Okhttp
的Response
一并封装成Retrofit
的Response
返回,最后把parseResponse
方法返回的Response
通过callback
回调出去,这是ExecutorCallbackCall
收到回调,通过线程切换执行器callbackExecutor
,切换到主线程执行callback
回调,一次异步请求就完成。
同步请求也是大同小异,只是少了一个回调。这里就不再分析。
关于Retrofit
的源码中,需要补充说明CallAdapter
、Converter
。这也是Retrofit
能在众多网络请求框架中脱颖而出深受欢迎的原因。
网络请求适配器,用于把默认的网络请求执行器的调用形式,适配成在不同平台下的网络请求执行器的调用形式,CallAdapter
的接口如下:
public interface CallAdapter<R, T> {
//返回响应body转换为Java对象时使用的类型
//例如Call, Type就是ResponseBody,Type是来自java.lang.reflect包的
Type responseType();
//把Call适配成T类型,就是将Retrofit的Call类型转为另外一个类型的Call
T adapt(Call<R> call);
//用于创建CallAdapter实例,通过get方法
abstract class Factory {
//根据Api接口定义的方法的返回值和注解信息,创建一个CallAdapter实例返回,如果这个Factory不能处理这个方法的返回值和注解信息,返回null,
//注意这里的returnType != 上面的responseType,例如Call,returnType的Type就是Call
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
//返回ParameterizedType的上限,即泛型类型的上限
//例如Call extends ResponseBody>, Type就是ResponseBody
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
//返回Type的原始类型
//例如Type为Call,返回Call.class
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
CallAdapter
接口很简单,只有2个方法responseType
、adapt
方法,和一个Factory
类,其中Factory
类的get
方法可以获取一个CallAdapter
实例,CallAdapter
的responseType
()方法可以获取T类型,这个Call
就是我们在定义Api接口方法时方法的返回参数.CallAdapter
的adapt
方法就是将传入的Call类型适配成另外一个我们期待的"Call",这里使用到了适配器模式.
适配器模式就是将两个因接口不兼容的类之间加上一个适配器,将一个类的接口变成客户端所期待的另外一个接口,从而使得他们工作在一起.至于怎么适配就需要看适配器中得adapt
方法的实现.
在Retrofit
中,CallAdapter
的默认实现是一个匿名类,可以通过CallAdapter
的Factory
获取,CallAdapter
的Factory
的默认实现是ExecutorCallAdapterFactory
,代码如下:
DefaultCallAdapterFactory .class
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
//线程切换执行器(在Retrofit的创建过程中已讲解)
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
//可以通过returnType获得responseType
//因为returnType = Call, 有了Call, 当然可以获得Call中的T,而T就是responseType
@Override public @Nullable CallAdapter<?, ?> get(
Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call or Call extends Foo>" );
}
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
return new CallAdapter<Object, Call<?>>() {
//返回一个CallAdapter的匿名类
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
//默认CallAdapter的adapt方法返回
return executor == null
? call
: new ExecutorCallbackCall<>(executor, call);
}
};
}
//网络请求执行器(在创建Api接口实例中中已经讲解)
static final class ExecutorCallbackCall<T> implements Call<T> {
// ....
}
}
在DefaultCallAdapterFactory
的get
方法中,new
了一个CallAdapter
返回,在CallAdapter
的adapt
方法实现中,new
了一个ExecutorCallbackCall
返回,并把入参call
和executor
传进了ExecutorCallbackCall
的构造方法中,ExecutorCallbackCall
就是一个实现了Call
接口的类,还是一个Call
,它就是Retrofit
的默认网络请求执行器,可以看到Retrofit
的默认的网络请求执行器适配,即adapt方法的默认实现就是用ExecutorCallbackCall包装传进来的Call
,并返回ExecutorCallbackCall
,这个传进来的Call
就是Call
的默认实现OkHttpCall
,在Retrofit
的构建过程中已经讲到。
既然CallAdapter
能把默认的网络请求执行器的调用形式,适配成在不同平台下的网络请求执行器的调用形式,那么它支持哪些平台呢?这个在retrofit-adapter
模块中可以找到答案,如下:
Retrofit
还支持guava
、java8
、rxjava
、scala
这四个平台(其中Android
中最常见为java8
、rxjava
)它们里面都各自实现了retrofit
模块暴露出去的CallAdapter
接口和CallAdapter
接口中的Factory
接口,在CallAdapter
的adapt
方法中提供各自平台的适配,我们可以通过addCallAdapterFactory
(Factory
)来添加不同平台的CallAdapter
工厂。
Converter
为数据转换器. Converter
把我们在Api
中方法注解和参数转化为网络请求执行器需要的参数类型,和把网络请求返回的数据转为我们需要的数据类型.
Converter
的接口如下:
public interface Converter<F, T> {
//把F转化为T,用于在网络请求中实现对象的转化
@Nullable T convert(F value) throws IOException;
//通过Factory 的responseBodyConverter或requestBodyConverter方法获得Converter实例或null
abstract class Factory {
//返回一个处理网络请求响应(Response)的body的Converter实例,如果不能处理这些类型(type)和注解,返回null
//这个Converter会把 ResponseBody 转化成 ?,这个ResponseBody是来自okhttp的
//例如使用GsonConverter,?代表某个java对象类型
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type,
Annotation[] annotations, Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to an HTTP request body, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Body @Body}, {@link Part @Part}, and {@link PartMap @PartMap}
* values.
*/
//返回一个处理网络请求(Request)的body的Converter实例,如果不能处理这些类型(type)和注解,返回null
//这个Converter会把 ?转化成 RequestBody,这个RequestBody是来自okhttp的
//这个Converter主要处理@Body、 @Part、@PartMap类型的注解
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
/**
* Returns a {@link Converter} for converting {@code type} to a {@link String}, or null if
* {@code type} cannot be handled by this factory. This is used to create converters for types
* specified by {@link Field @Field}, {@link FieldMap @FieldMap} values,
* {@link Header @Header}, {@link HeaderMap @HeaderMap}, {@link Path @Path},
* {@link Query @Query}, and {@link QueryMap @QueryMap} values.
*/
//返回一个处理网络请求(Request)的body的Converter实例
//这个Converter会把 ?转化成 String
//这个Converter主要处理@Field、@FieldMap、@Header、HeaderMap @HeaderMap、@Path、@Query、@QueryMap类型的注解
public @Nullable Converter<?, String> stringConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
return null;
}
//下面两个方法和上面CallAdapter的Factory中同名方法的意思一样
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
Converter
接口也很简单,只有一个convert
方法,和一个Factory
类.
因为Converter
要提供2个方向数据的转化,所以Factory
提供了2个方法分别用于获取不同方向的转化,其中**responseBodyConverter
方法就是获得一个把网络返回的数据转化为我们需要的数据类型的Converter
实例,而requestBodyConverter
方法就是获得一个把我们在Api接口定义的方法注解和参数转化为网络请求的Converter
实例,**那么要怎么转化呢?就要看Converter
的convert
方法的实现,convert
方法把F类型 转化为 T类型,接下来我们看convert方法在Retrofit
中的默认实现。
Converter
在Retrofit
的默认实现有五个,都是Converter
的Factory
的内部类,可通过Converter
的Factory
获得,Converter
的Factory
的默认实现是BuiltInConverters
,如下:
final class BuiltInConverters extends Converter.Factory {
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit Retrofit) {
if (type == ResponseBody.class) {
//支持ResponseBody类型的转化
//如果是二进制流形式,就返回StreamingResponseBodyConverter实例
//如果是字符流形式,就返回BufferingResponseBodyConverter实例
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
//支持Void类型的转化
//返回VoidResponseBodyConverter实例
return VoidResponseBodyConverter.INSTANCE;
}
//除了以上两种类型,其他类型都不支持,返回null
return null;
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit Retrofit) {
//支持向RequestBody类型转化
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
//返回RequestBodyConverter实例
return RequestBodyConverter.INSTANCE;
}
//除了RequestBody类型,不支持向其他类型转化,返回null
return null;
}
static final class VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();
@Override public Void convert(ResponseBody value) {
value.close();
return null;
}
}
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
@Override public RequestBody convert(RequestBody value) {
return value;
}
}
static final class StreamingResponseBodyConverter
implements Converter<ResponseBody, ResponseBody> {
static final StreamingResponseBodyConverter INSTANCE = new StreamingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) {
return value;
}
}
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();
}
}
}
BuiltInConverters
实现了Factory
中的responseBodyConverter
和requestBodyConverter
方法,内部含有五个Converter
默认实现类,在Factory
的responseBodyConverter
和requestBodyConverter
方法中分别返回这几Converter
实例,其中只有ToStringConverter
没有使用到,我们还发现了这五个Converter
的convert
方法的实现除了BufferingResponseBodyConverter
,大部分都是,入参是是什么,返回就是什么,所以Retrofit
中Converter
默认实现的convert
方法大部分都没有对数据进行转化,返回原始数据,这些原始数据是String
或来自Okhttp
的ResponseBody
、RequestBody
,例如ResponseBodyConverter
的convert
方法就是返回Okhttp
的ResponseBody
,RequestBodyConverter
的convert
方法就是返回Okhttp
的RequestBody
。
Converter
除了默认的返回原始数据,它还支持哪些数据转化呢?这个在retrofit-converters
模块中可以找到答案,如下:
可以看到Retrofit
还支持json
、xml
、protobuf
等多种数据类型的转化,这些子模块都各自实现了retrofit
模块暴露出来的Converter
接口和Converter
接口中的Factory
接口,在Converter
的adapt
方法中实现不同数据类型的转化逻辑,我们可以通过addConverterFactory(Factory)
来支持不同数据类型转化的Converter
工厂。
从整体来看,Retrofit
的流程并不复杂,它的使用也非常简单.这主要得益于它优秀的框架,以及多种设计模式的巧妙运用.
其中最大的亮点就是动态代理模式,通过一个代理类InvocationHandler
代理N多个接口,它把每一个方法的处理逻辑都集中到了invoke
方法中,这样就能在同一处地方处理所有方法的注解解析。
而Retrofit
之所以这么受到编程人员的欢迎,很大程度是因为它CallAdapter
、Converter
的引入,并且还是ArrayList
集合的形式,它的高度灵活性,成为一款百搭网络请求库。
到此,Retrofit
的整体流程分析完毕。