本篇文章使用的是Retrofit 2.3.0版本。Retrofit是基于okhttp的一个RESTful的HTTP网络请求框架的封装,内部的网络请求还是由okhttp完成的,对OkHttp不了解的可以看看:
Retrofit封装了接口层的请求参数以及请求结果的解析及转换(支持Gson、XML、JSON、protobuf等)等。
本文目的:
①retrofit是怎么将方法及其参数转化为请求的?
②retrofit.create得到的类是什么?
我们以Retrofit基本的用法作为入口:
//创建retrofit对象
Retrofit retrofit = new Retrofit.Builder()
//使用自定义的mGsonConverterFactory
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://apis.baidu.com/txapi/")
.build();
// 实例化我们的mApi对象
mApi = retrofit.create(APi.class);
// 调用我们的响应的方法
Call<News> news = mApi.getNews(number, page);
news.enqueue(new Callback<News>() {
@Override
public void onResponse(Call<News> call, Response<News> response) {
News body = response.body();
Logger.i("onResponse: ="+body.toString());
}
@Override
public void onFailure(Call<News> call, Throwable t) {
Logger.i("onResponse: ="+t.getMessage());
}
});
可以看到Retrofit类使用建造者模式(Build模式)初始化对象,我们先看一下Retrofit类:
public final class Retrofit {
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
final List<Converter.Factory> converterFactories;
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;
}
}
ServiceMethod:网络请求配置对象,包含相关的配置(如请求头、请求方法、请求的参数等)
okhttp3.Call.Factory:网络请求的工厂,生成网络请求的Call,默认是OkHttpClient,这个应该不陌生,学过OkHttpClient的都知道OkHttpClient用来配置缓存、拦截器等。
Converter.Factory:生成数据装换器,比如:将请求结果转化为JSON、XML等,这里我们用GsonConverterFactory做例子
CallAdapter.Factory:生成网络请求适配器,将网络请求执行器OkHttpCall转换成适合不同平台来调用的网络请求执行器。Retrofit支持Android、RxJava、java8、Guava等平台,所以Retrofit提供了四中CallAdapterFactory、ExecutorCallAdapterFactory、GuavaCallAdapterFactory、Java8CallAdapterFactory。默认情况下是ExecutorCallAdapterFactory,如果使用RxJava2CallAdapter,请求会被转换为Observable对象。
callbackExecutor:回调方法执行器,将请求结果使用Handler传回到主线程。
在下面的分析中我们将会看到这些类的使用。
接着我们看一下new Retrofit.Builder()
public Builder() {
this(Platform.get());
}
Platform.get()调用findPlatform方法:
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
Class.forName()是要求JVM查找并加载某个类并执行该类的静态代码段。如果是Android平台则返回一个Android对象,Android对象也是继承Platform:
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);
}
}
}
Platform的主要作用是当没有指定特定的回调方法执行器CallbackExecutor和网络请求适配器CallAdapterFactory时用来获取一个默认的CallbackExecutor和CallAdapterFactory,分别是MainThreadExecutor(将Runnable从子线程切换到主线程执行)和ExecutorCallAdapterFactory(这个之后会用到)
Retrofit的配置过程我们就不看了,直接看Builder的build方法:
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> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
可以看到默认的callFactory是OkHttpClient,默认的callbackExecutor从platform获取,添加一个默认的CallAdapterFactory,调用Retrofit的构造函数,传入参数并返回Retrofit对象。
Retrofit构造完成后,接着看我们的代码:
//创建retrofit对象
Retrofit retrofit = new Retrofit.Builder()
//使用自定义的mGsonConverterFactory
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://apis.baidu.com/txapi/")
.build();
// 实例化我们的mApi对象
mApi = retrofit.create(APi.class);
调用Retrofit的create方法,传入我们的接口类:
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);//验证接口是否有效
if (validateEagerly) {
//用接口的每个方法生成一个ServiceMethod并放入Map类对象serviceMethodCache中
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);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//关键
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
可以看到先调用validateServiceInterface验证接口是否有效,然后调用eagerlyValidateMethods方法:
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {//遍历每个方法
if (!platform.isDefaultMethod(method)) {//排除默认方法
loadServiceMethod(method);
}
}
}
ServiceMethod<?, ?> loadServiceMethod(Method method) {
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//创建ServiceMethod对象
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
遍历接口的每个方法,为每个方法创建一个ServiceMethod对象,并放入serviceMethodCache中。我们看看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);
final okhttp3.Call.Factory callFactory;
final CallAdapter<R, T> callAdapter;
private final HttpUrl baseUrl;
private final Converter<ResponseBody, R> responseConverter;
private final String httpMethod;
private final String relativeUrl;
private final Headers headers;
private final MediaType contentType;
private final boolean hasBody;
private final boolean isFormEncoded;
private final boolean isMultipart;
private final ParameterHandler<?>[] parameterHandlers;
...
}
可以看到这个类包含了url、请求结果转换器、请求方法、请求头、注解等信息。我们看一下它的Builder:
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();
responseType = callAdapter.responseType();
...
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
...
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);
}
构造方法获取方法的注解、参数、参数的注解。
在build方法中,调用createCallAdapter方法,createCallAdapter方法调用retrofit的callAdapter方法获取CallAdapter:
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
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++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
...
}
这里的参数returnType是我们的接口方法的返回类型,比如,Call<ResponseBody>。遍历retrofit中adapterFactories列表获取CallAdapter.Factory并调用get方法生成一个CallAdapter并返回,这里我们以默认的ExecutorCallAdapterFactory为例:
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
这里调用Utils的getCallResponseType方法获得方法返回类型中参数化类型的Type:
static Type getCallResponseType(Type returnType) {
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
"Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
}
return getParameterUpperBound(0, (ParameterizedType) returnType);
}
比如:如果method的返回类型为Call<Foo>或者Call<? extends Foo>,则这个方法返回Foo类的Type。并使CallAdapter的responseType返回该类型。
我们回到ServiceMethod.Builder的build方法,获取CallAdapter后,调用callAdapter的responseType获取返回类型中参数化类型的Type,然后调用createResponseConverter方法,createResponseConverter方法又调用Retrofit的responseBodyConverter方法,通过converterFactories获取一个Converter.Factory,并调用responseBodyConverter获取一个Converter对象,过程和获取CallAdapter时差不多,这里就赘述了。
回到ServiceMethod.Builder的build方法,
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
responseConverter = createResponseConverter();
//解析方法注解
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
...
//解析参数注解
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);
}
调用parseMethodAnnotation解析方法的注解,获得httpMethod等信息,然后再解析参数的注解,调用parseParameter,为每一个参数生成一个ParameterHandler对象,存放于ParameterHandler数组中。总结:ServiceMethod解析并存放接口方法的网络请求信息。
接下来回到Retrofit的create方法:
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.callAdapter.adapt(okHttpCall);
}
});
}
create方法返回我们接口的代理对象,当我们该代理对象的方法时,就会调用它的invoke方法,先获取方法的ServiceMethod对象,然后构造一个OkHttpCall对象,调用ServiceMethod的callAdapter对象的adapter方法,这里我们以默认的CallAdapter为例,也就是ExecutorCallAdapterFactory生成的CallAdapter:
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
可以看到它的adapt方法返回一个ExecutorCallbackCall对象(继承自Call),内存存放我们传入的OkHttpCall对象。当我们调用该Call对象的execute方法执行请求时,ExecutorCallbackCall对象内部还是调用OkHttpCall对象的execute方法:
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
...
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException e) {
creationFailure = e;
throw e;
}
}
}
if (canceled) {
call.cancel();
}
return parseResponse(call.execute());
}
createRawCall方法通过serviceMethod中请求的信息构造一个请求并返回。然后执行该请求的execute方法获取响应,获取响应的流程就是通过Okhttp来获取的。得到响应后,利用Converter解析响应得到想要的格式。
总结:Retrofit的分析就到这里,主要通过反射获取注解的信息,构造请求,还有Converter和CallAdapter的作用,CallAdapter在代理的invoke方法返回时起作用,将返回类型转换为特定的类型(如Call<R>、或者Rxjava的Observer),Converter在获取响应之后将结果转换为特定的格式(如ResponseBody等)。