版权声明:本文为博主原创文章,未经博主容许不得转载
文章分类:Android知识体系 - 网络编程
复制代码
Retrofit是一个基于OkHttp、遵循RESTful API设计风格的网络请求封装框架,本文将按照其工做流程逐步分析对应的源码(本文使用的Retrofit版本为2.5.0)java
如下是一次简单的请求示例,首先咱们须要定义一个接口API,并使用注解描述其中的API方法android
public interface ExpressService {
@GET("query")
Call<ResponseBody> get(@Query("type") String type, @Query("postid") String postid);
}
复制代码
而后是Retrofit的工做流,能够分为三步:express
public void asyncGet() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.kuaidi100.com/")
.build();
ExpressService expressService = retrofit.create(ExpressService.class);
Call<ResponseBody> call = expressService.get("ems", "11111111");
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
复制代码
下面咱们将按照上述过程,分析对应的源码编程
本章咱们将分析Retrofit对象构建的过程,如下是对应的示例代码缓存
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.kuaidi100.com/")
.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> callAdapterFactories;
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
...
}
复制代码
serviceMethodCache:serviceMethodCache是一个ConcurrentHashMap类型的Map集合,所以它支持并发操做且线程安全,其存储对象是ServiceMethod。ServiceMethod咱们能够理解是API方法的配置器以及代理中转站,具体内容会在后文进行分析bash
callFactory:callFactory就是生产请求执行器的工厂(Call.Factory),Retrofit中默认的请求执行器工厂是OkHttpClient。若是咱们没有设置自定义的请求执行器工厂,那么就会在构建Retrofit对象的过程当中为咱们建立一个OkHttpClient实例网络
baseUrl:API接口基地址的封装对象,类型为HttpUrl并发
converterFactories:数据转换器工厂(Converter.Factory)的集合,该工厂的产品数据转换器(Converter)做用是对请求与响应数据进行序列化和反序列化app
callAdapterFactories:请求适配器工厂(CallAdapter.Factory)的集合,该工厂的产品请求适配器(CallAdapter)用于改变执行请求的方式,例如咱们能够经过添加支持RxJava的请求适配器,将默认执行请求的方式改成RxJava调用链的方式
callbackExecutor:回调执行器,主要做用是处理请求回调,例如将回调所在线程从子线程切换至主线程
validateEagerly:是否提早加载API方法配置的标志位
Retrofit对象经过建造者模式进行构建,咱们来看下Builder是如何初始化的
public static final class Builder {
private final Platform platform;
...
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
...
}
复制代码
咱们看见Builder的构造方法须要传入Platform对象,它的主要做用是根据运行平台为Retrofit提供默认的配置方法、工厂类或者工厂类的集合。Platform能够经过Platform.get()
方法获取实例,咱们来看下方法相关源码
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
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();
}
...
}
复制代码
调用Platform.get()
方法获取的是静态成员变量PLATFORM,PLATFORM则经过findPlatform()
方法生成
findPlatform()
主要经过是否能查找到指定的类来判断当前Retrofit运行的平台,若是是运行在Android平台,则返回Platform.Android的实例;若是是Java平台,则返回Platform.Java8的实例;若是二者皆非,则返回Platform自身的实例
如今咱们是在Android平台下运行Retrofit,因此继续往下看Platform.Android的代码
// Platform
static class Android extends Platform {
@IgnoreJRERequirement // Guarded by API check.
@Override
boolean isDefaultMethod(Method method) {
if (Build.VERSION.SDK_INT < 24) {
return false;
}
return method.isDefault();
}
@Override
public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override
List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);
return Build.VERSION.SDK_INT >= 24
? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
: singletonList(executorFactory);
}
@Override
int defaultCallAdapterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
}
@Override
List<? extends Converter.Factory> defaultConverterFactories() {
return Build.VERSION.SDK_INT >= 24
? singletonList(OptionalConverterFactory.INSTANCE)
: Collections.<Converter.Factory>emptyList();
}
@Override
int defaultConverterFactoriesSize() {
return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
}
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()
完成构建时用到,具体的咱们待会再细说,如今先来看下Builder主要提供了哪些方法
// Retrofit.Builder
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
return baseUrl(HttpUrl.get(baseUrl));
}
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
复制代码
简单介绍一下这些方法的做用
client()
:添加自定义配置的OkHttpClientcallFactory()
:添加自定义的请求执行器工厂baseUrl()
:添加API接口的基地址addConverterFactory()
:添加自定义的数据转换器addCallAdapterFactory()
:添加自定义的请求适配器callbackExecutor()
:添加自定义的回调执行器validateEagerly()
:设置是否预加载API方法的标志位完成Retrofit的构建最终须要调用Builder.build()
方法,来看下源码
// Retrofit.Builder
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.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// 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);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
复制代码
build()
方法完成了如下工做:
Platform.defaultCallbackExecutor()
,即MainThreadExecutor完成上述工做后将相关参数传入Retrofit的构造方法中即完成构建Retrofit对象的工做。其中须要注意的是converterFactories和callAdapterFactories都变成了不可修改的List集合,这意味着后续咱们不能够再更改这两个集合中的内容了
至此Retrofit对象构建的过程就分析完了,下一章咱们将分析API接口方法加载配置以及转换为请求执行器的过程
这一章咱们分析了构建Retrofit对象的过程,过程当中主要完成了如下工做:
本章咱们将分析API方法加载配置的过程,如下是对应的示例代码
// 请求示例
ExpressService expressService = retrofit.create(ExpressService.class);
Call<ResponseBody> call = expressService.get("ems", "11111111");
复制代码
Retrofit对象构建完毕后,下一步是经过Retrofit.create(Class<T> service)
方法实现API接口,该方法的代码以下
// Retrofit
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();
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);
}
});
}
复制代码
该方法主要是经过运用动态代理的方式为请求接口生成一个代理对象,咱们对接口全部方法的调用都会转发到代理对象中。如今咱们一步步分析是如何完成整个动态代理的过程的
首先是调用Utils.validateServiceInterface(Class<T> service)
对接口类进行校验
// Utils
static <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
复制代码
这里规定咱们传入的参数必须是一个接口类,而且该接口不能继承其余的接口
回到create方法中,接下来会经过标志位validateEagerly来决定是否提早为API方法加载相应的配置
// Retrofit.create
if (validateEagerly) {
eagerlyValidateMethods(service);
}
复制代码
咱们知道动态代理是在接口方法被调用时才会生效的,这相似于懒加载策略,Retrofit默认采用的就是这种方式,而咱们能够经过Retrofit.Builder.validateEagerly()
方法将validateEagerly标志设置为true,Retrofit就会调用eagerlyValidateMethods()
提早为接口方法加载配置
eagerlyValidateMethods()
源码以下
// Retrofit
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method) && !Modifier.isStatic(method.getModifiers())) {
loadServiceMethod(method);
}
}
}
复制代码
具体逻辑为遍历接口中的方法(method),而后判断方法是否为默认方法或静态方法(接口的默认方法和静态方法都是Java8新增的特性),若不是则调用loadServiceMethod()
为接口方法加载相应的配置。loadServiceMethod()
方法的逻辑咱们待会再细说,如今继续分析Retrofit.create()
方法
通过预加载的逻辑后,下一步就是执行动态代理相关的逻辑
// Retrofit.create
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);
}
});
复制代码
首先依然是对接口方法的校验,会判断这次调用的方法是否为Object对象的方法(非接口方法),如果则正常调用,不进行任何代理操做。而后判断该方法是否为默认方法,如果则调用Platform对象提供的配置方法invokeDefaultMethod()
并返回。invokeDefaultMethod()
在Android平台下会抛出UnsupportedOperationException异常,具体代码以下
// Platform
@Nullable
Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object, @Nullable Object... args) throws Throwable {
throw new UnsupportedOperationException();
}
复制代码
执行完全部的校验工序以后,最终依然是调用loadServiceMethod()
开始加载API方法的配置,咱们来看下源码
ServiceMethod<?> loadServiceMethod(Method method) {
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
复制代码
方法的逻辑很是简单,功能能够分为两部分来看
继续往下看ServiceMethod的代码
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(method,
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError(method, "Service methods cannot return void.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
复制代码
ServiceMethod是一个抽象类,它只有两个方法,一个是invoke()
,这是一个抽象方法,具体的逻辑由ServiceMethod的子类实现,当调用接口方法时会被动态代理到这个方法中
另外一个方法是parseAnnotations()
,这是一个静态方法,它的功能以下
RequestFactory.parseAnnotations()
方法HttpServiceMethod.parseAnnotations()
完成接口方法后续的配置加载工做这一部分最主要的关注点是RequestFactory。RequestFactory是请求体对象(okhttp3.Request)的工厂类,咱们能够调用RequestFactory.create()
建立一个请求体的实例,下面咱们就来详细分析生成RequestFactory的过程
如下是与RequestFactory.parseAnnotations()
方法相关的代码
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
...
RequestFactory(Builder builder) {
method = builder.method;
baseUrl = builder.retrofit.baseUrl;
httpMethod = builder.httpMethod;
relativeUrl = builder.relativeUrl;
headers = builder.headers;
contentType = builder.contentType;
hasBody = builder.hasBody;
isFormEncoded = builder.isFormEncoded;
isMultipart = builder.isMultipart;
parameterHandlers = builder.parameterHandlers;
isKotlinSuspendFunction = builder.isKotlinSuspendFunction;
}
...
static final class Builder {
...
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
RequestFactory build() {
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(method,
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError(method, "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, lastParameter = parameterCount - 1; p < parameterCount; p++) {
parameterHandlers[p] =
parseParameter(p, parameterTypes[p], parameterAnnotationsArray[p], p == lastParameter);
}
if (relativeUrl == null && !gotUrl) {
throw methodError(method, "Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError(method, "Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError(method, "Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError(method, "Multipart method must contain at least one @Part.");
}
return new RequestFactory(this);
}
...
}
}
复制代码
RequestFactory一样经过建造者模式来构建实例,咱们能够看到Builder.build()
方法中有许多状态位的校验逻辑,主要做用是当用户在建立请求接口中错误地使用注解或配置参数时,能够抛出相应的异常告知用户。这部分的细节就不一一查看了,感兴趣的同窗能够自行研究
这里咱们最主要关注的地方有两点:一是遍历接口方法的注解,而后经过Builder.parseMethodAnnotation()
方法解析注解的过程;二是遍历方法的参数,而后经过Builder.parseParameter()
方法解析参数的过程
首先来看第一点,parseMethodAnnotation()
的代码以下
// RequestFactory.Builder
private void parseMethodAnnotation(Annotation annotation) {
if (annotation instanceof DELETE) {
parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
} else if (annotation instanceof GET) {
parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
} else if (annotation instanceof HEAD) {
parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
} else if (annotation instanceof PATCH) {
parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
} else if (annotation instanceof POST) {
parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
} else if (annotation instanceof PUT) {
parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
} else if (annotation instanceof OPTIONS) {
parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
} else if (annotation instanceof HTTP) {
HTTP http = (HTTP) annotation;
parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
} else if (annotation instanceof retrofit2.http.Headers) {
String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
if (headersToParse.length == 0) {
throw methodError(method, "@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
复制代码
这里有大量的判断分支语句,咱们能够按照注解的功能分红三类来看。第一类注解主要是描述HTTP方法的,例如@DELETE
、@GET
、@POST
等,解析方法为parseHttpMethodAndPath()
,来看下源码
// RequestFactory.Builder
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null) {
throw methodError(method, "Only one HTTP method is allowed. Found: %s and %s.",
this.httpMethod, httpMethod);
}
this.httpMethod = httpMethod;
this.hasBody = hasBody;
if (value.isEmpty()) {
return;
}
// Get the relative URL path and existing query string, if present.
int question = value.indexOf('?');
if (question != -1 && question < value.length() - 1) {
// Ensure the query string does not have any named parameters.
String queryParams = value.substring(question + 1);
Matcher queryParamMatcher = PARAM_URL_REGEX.matcher(queryParams);
if (queryParamMatcher.find()) {
throw methodError(method, "URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
复制代码
这个方法有三个参数
@GET("query?type=ems&postid=11111111")
中括号里的内容实际上就是指服务端接口Url的资源路径和查询参数部分。这些内容能够经过调用这一系列注解的value()
方法获取,这是在定义注解时设置的知道了每一个参数的含义,后面的代码就好理解了,流程是这样的:首先会对一个接口方法是否同时设置了多个HTTP方法注解进行了校验;而后校验value是否为空,为空就不须要继续解析了,由于这部份内容不是在方法注解里设置就是在方法参数中设置,这里没有,那就直接交给后面解析参数时再去处理;若value不为空,则校验查询参数部分是否符合要求,符合要求则继续解析查询参数字符串获得参数集合,不符合则抛出异常,这些操做主要经过Java正则解析相关的Matcher类完成的,就不细说了
回到RequestFactory.Builder.parseMethodAnnotation()
,咱们来看第二类注解。第二类注解只有@Headers
一个,负责设置请求头信息,解析的方法为Builder.parseHeaders()
,这部份内容比较简单,就不展开了
第三类注解主要负责描述请求报文数据的类型,有@Multipart
和@FormUrlEncoded
两种,但由于这两种类型都须要配合方法参数的注解使用,因此这里的处理过程只是简单地校验二者不重复设置就行
实际上方法注解中还有第四类,那就是@Streaming
,这是用于描述响应正文数据的,所以Retrofit将它的处理过程放到了后面配置响应内容相关的部分再进行
至此解析方法注解的部分咱们就分析完了,接下来看解析参数的部分
解析方法参数对应的方法是Builder.parseParameter()
,代码以下
// RequestFactory.Builder
private @Nullable ParameterHandler<?> parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler<?> result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction =
parseParameterAnnotation(p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(method, p,
"Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
}
...
return result;
}
复制代码
这里的核心逻辑是经过parseParameterAnnotation()
方法解析参数注解生成ParameterHandler对象,同时规定一个参数只能设置一个Retrofit定义的注解
ParameterHandler是一个抽象类,它的子类封装了参数的数据和数据的处理过程,而且和不一样注解类型的参数一一对应,例如子类ParameterHandler.Query封装了@Query
注解的参数,ParameterHandler.Field则封装了@Field
注解的参数
做为参数的处理器,ParameterHandler能够在构建请求体对象时利用专属的参数数据转换器将数据转换成请求须要的格式,这里咱们以ParameterHandler.Query为例进行分析
// ParameterHandler
static final class Query<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
private final boolean encoded;
Query(String name, Converter<T, String> valueConverter, boolean encoded) {
this.name = checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
@Override
void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) return; // Skip null values.
String queryValue = valueConverter.convert(value);
if (queryValue == null) return; // Skip converted but null values
builder.addQueryParam(name, queryValue, encoded);
}
}
复制代码
ParameterHandler.Query有三个成员属性,其中name和encoded对应了@Query
定义的属性
@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Query {
/** The query parameter name. */
String value();
/** * Specifies whether the parameter {@linkplain #value() name} and value are already URL encoded. */
boolean encoded() default false;
}
复制代码
而valueConverter指的就是参数数据转换器,它能够经过调用convert()
方法进行数据转换。参数处理的过程都放在Query.apply()
方法中,当构建请求体须要此参数的数据时,就会调用apply()
方法,而后经过传入的RequestBuilder引用设置数据
ParameterHandler的分析就到这,其余参数处理器就不一一分析了,由于套路基本上都是同样的,如今咱们继续分析parseParameterAnnotation()
方法是如何生成ParameterHandler的
// RequestFactory.Builder
@Nullable
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Url) {
...
return new ParameterHandler.RelativeUrl(method, p);
} else if (annotation instanceof Path) {
...
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());
} else if (annotation instanceof Query) {
...
if (Iterable.class.isAssignableFrom(rawParameterType)) {
...
Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
...
Converter<?, String> converter = retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).array();
} else {
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Query<>(name, converter, encoded);
}
} else if (annotation instanceof QueryName) {
...
if (Iterable.class.isAssignableFrom(rawParameterType)) {
...
Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.QueryName<>(converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
...
Converter<?, String> converter = retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.QueryName<>(converter, encoded).array();
} else {
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.QueryName<>(converter, encoded);
}
} else if (annotation instanceof QueryMap) {
...
Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);
return new ParameterHandler.QueryMap<>(method, p,
valueConverter, ((QueryMap) annotation).encoded());
} else if (annotation instanceof Header) {
...
if (Iterable.class.isAssignableFrom(rawParameterType)) {
...
Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Header<>(name, converter).iterable();
} else if (rawParameterType.isArray()) {
...
Converter<?, String> converter = retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Header<>(name, converter).array();
} else {
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Header<>(name, converter);
}
} else if (annotation instanceof HeaderMap) {
...
Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);
return new ParameterHandler.HeaderMap<>(method, p, valueConverter);
} else if (annotation instanceof Field) {
...
if (Iterable.class.isAssignableFrom(rawParameterType)) {
...
Converter<?, String> converter = retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Field<>(name, converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
...
Converter<?, String> converter = retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Field<>(name, converter, encoded).array();
} else {
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Field<>(name, converter, encoded);
}
} else if (annotation instanceof FieldMap) {
...
Converter<?, String> valueConverter = retrofit.stringConverter(valueType, annotations);
return new ParameterHandler.FieldMap<>(method, p, valueConverter, ((FieldMap) annotation).encoded());
} else if (annotation instanceof Part) {
...
String partName = part.value();
if (partName.isEmpty()) {
if (Iterable.class.isAssignableFrom(rawParameterType)) {
...
return ParameterHandler.RawPart.INSTANCE.iterable();
} else if (rawParameterType.isArray()) {
...
return ParameterHandler.RawPart.INSTANCE.array();
} else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
return ParameterHandler.RawPart.INSTANCE;
} else {
...
}
} else {
Headers headers =
Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
"Content-Transfer-Encoding", part.encoding());
if (Iterable.class.isAssignableFrom(rawParameterType)) {
...
Converter<?, RequestBody> converter =
retrofit.requestBodyConverter(iterableType, annotations, methodAnnotations);
return new ParameterHandler.Part<>(method, p, headers, converter).iterable();
} else if (rawParameterType.isArray()) {
...
Converter<?, RequestBody> converter =
retrofit.requestBodyConverter(arrayComponentType, annotations, methodAnnotations);
return new ParameterHandler.Part<>(method, p, headers, converter).array();
} else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
...
} else {
Converter<?, RequestBody> converter =
retrofit.requestBodyConverter(type, annotations, methodAnnotations);
return new ParameterHandler.Part<>(method, p, headers, converter);
}
}
} else if (annotation instanceof PartMap) {
...
Converter<?, RequestBody> valueConverter =
retrofit.requestBodyConverter(valueType, annotations, methodAnnotations);
return new ParameterHandler.PartMap<>(method, p, valueConverter, partMap.encoding());
} else if (annotation instanceof Body) {
...
Converter<?, RequestBody> converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
return new ParameterHandler.Body<>(method, p, converter);
} else if (annotation instanceof Tag) {
...
return new ParameterHandler.Tag<>(tagType);
}
return null; // Not a Retrofit annotation.
}
复制代码
因为方法注解不少,parseParameterAnnotation()
代码很是的多,所以这里我只把核心的内容展现给你们。parseParameterAnnotation()
解析每一个参数的过程大体能够总结为三步
校验过程就不细说了,感兴趣的同窗能够自行查阅源码,咱们重点关注参数数据转换器是如何生成的。从上面的源码能够看出生成转换器的方式主要有两种,一种是经过Retrofit.stringConverter()
方法生成,这类转换器转换出来的数据类型为String;另外一种则经过Retrofit.requestBodyConverter()
方法生成,对应的转换结果就是请求实体类型RequestBody
先来看Retrofit.stringConverter()
// Retrofit
public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
for (int i = 0, count = converterFactories.size(); i < count; i++) {
Converter<?, String> converter =
converterFactories.get(i).stringConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<T, String>) converter;
}
}
// Nothing matched. Resort to default converter which just calls toString().
//noinspection unchecked
return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
}
复制代码
这里的代码主要完成了如下工做:按顺序遍历数据转换器工厂集合converterFactories,到符合要求的转换器工厂,即在实现接口方法Converter.Factory.stringConverter()
时不能返回null。这里有一点细节须要注意,在遍历过程当中只要发现符合的转换器工厂就会返回,所以转换器工厂添加的顺序决定了它们的优先级,越早添加的优先级越高,就能够优先被征调。还记得咱们在构建Retrofit对象时添加的转换器吗?如今咱们从新来回顾一下加深记忆
// Retrofit.Builder.build()
converterFactories.add(new BuiltInConverters());// 添加Retrofit内置的数据转换器,优先级最高
converterFactories.addAll(this.converterFactories);// 按顺序添加全部自定义的数据转换器
converterFactories.addAll(platform.defaultConverterFactories());// 添加针对对应运行平台设置的数据转换器工厂
复制代码
当内置转换器工厂BuiltInConverters以及集合中其余转换器工厂都不符合要求时,则返回特定的转换器BuiltInConverters.ToStringConverter,其代码以下
// BuiltInConverters
static final class ToStringConverter implements Converter<Object, String> {
static final ToStringConverter INSTANCE = new ToStringConverter();
@Override
public String convert(Object value) {
return value.toString();
}
}
复制代码
代码很简单就不细说了,接下来是Retrofit.requestBodyConverter()
public <T> Converter<T, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
return nextRequestBodyConverter(null, type, parameterAnnotations, methodAnnotations);
}
public <T> Converter<T, RequestBody> nextRequestBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
checkNotNull(type, "type == null");
checkNotNull(parameterAnnotations, "parameterAnnotations == null");
checkNotNull(methodAnnotations, "methodAnnotations == null");
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter.Factory factory = converterFactories.get(i);
Converter<?, RequestBody> converter =
factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<T, RequestBody>) converter;
}
}
// 没有找到符合要求的请求数据转换器,抛出IllegalArgumentException异常
...
}
复制代码
和以前的处理逻辑差异不大,不过此次调用的方法为Converter.Factory.requestBodyConverter()
,并且咱们发现BuiltInConverters实现了该接口方法,代码以下
// BuiltInConverters
@Override
public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return RequestBodyConverter.INSTANCE;
}
return null;
}
复制代码
这里返回了针对RequestBody类型参数的转换器BuiltInConverters.RequestBodyConverter
// BuiltInConverters
static final class RequestBodyConverter implements Converter<RequestBody, RequestBody> {
static final RequestBodyConverter INSTANCE = new RequestBodyConverter();
@Override
public RequestBody convert(RequestBody value) {
return value;
}
}
复制代码
能够看见RequestBodyConverter并无对参数数据进行任何处理,所以该转换器最主要的做用是拦截类型为RequestBody的参数
至此咱们就完了解析方法参数的所有工做,也成功生成了请求体对象工厂RequestFactory。
HttpServiceMethod是ServiceMethod的子类,它的代码有点多,咱们直接挑重点看。首先是parseAnnotations()
方法
// HttpServiceMethod
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations( Retrofit retrofit, Method method, RequestFactory requestFactory) {
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method);
Type responseType = callAdapter.responseType();
...
Converter<ResponseBody, ResponseT> responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
return new HttpServiceMethod<>(requestFactory, callFactory, callAdapter, responseConverter);
}
复制代码
这里主要作了下面这些工做
createCallAdapter()
方法生成请求适配器callAdaptercallAdapter.responseType()
方法获取响应数据的类型responseTypecreateResponseConverter()
方法生成响应体(Response)的数据转换器responseConverter首先咱们分析生成请求适配器CallAdapter的过程,如下是createCallAdapter()
方法的代码
// HttpServiceMethod
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter( Retrofit retrofit, Method method) {
Type returnType = method.getGenericReturnType();
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create call adapter for %s", returnType);
}
}
复制代码
// Retrofit
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
...
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
// 当全部适配器都不符合要求时抛出IllegalArgumentException异常
...
}
复制代码
能够发现套路基本上是同样的,具体方式为遍历callAdapterFactories找到符合要求的请求适配器后返回,验证的方法为CallAdapter.Factory.get()
。经过上一章的分析咱们知道,除了用户添加的自定义的请求适配器工厂之外,Retrofit还内置了两种默认的适配器工厂:CompletableFutureCallAdapterFactory(系统版本大于等于24时生效)和ExecutorCallAdapterFactory。这里咱们只以ExecutorCallAdapterFactory为例进行分析,来看下源码
final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
final Executor callbackExecutor;
ExecutorCallAdapterFactory(Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@Override
public @Nullable
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);
}
};
}
...
}
复制代码
经过上述代码咱们知道,get()
方法指定ExecutorCallAdapterFactory的适配目标是返回类型为retrofit2.Call的API方法,其最终返回值是一个新的CallAdapter实例。此外,该CallAdapter实例的adapt()
方法生成了retrofit2.Call的子类ExecutorCallbackCall,这其实是请求执行器的装饰器,具体内容咱们在后面用到时再细说,如今继续下一步
接下来是调用HttpServiceMethod.createResponseConverter()
方法生成响应数据转换器(ResponseConverter),咱们来看下相关代码
// HttpServiceMethod
private static <ResponseT> Converter<ResponseBody, ResponseT> createResponseConverter( Retrofit retrofit, Method method, Type responseType) {
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(method, e, "Unable to create converter for %s", responseType);
}
}
复制代码
// Retrofit
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter( @Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
// 没法找到符合要求的ResponseBodyConverter时抛出IllegalArgumentException异常
...
}
复制代码
一样这里也是经过遍历转换器工厂集合converterFactories找到符合要求的转换器工厂,验证方法为Converter.Factory.responseBodyConverter()
。以前讲过转换器工厂优先级最高的是内置的BuiltInConverters,来看下它的responseBodyConverter()
方法
final class BuiltInConverters extends Converter.Factory {
...
@Override
public @Nullable Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? StreamingResponseBodyConverter.INSTANCE
: BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return VoidResponseBodyConverter.INSTANCE;
}
...
return null;
}
...
}
复制代码
这里指定BuiltInConverters只能处理类型为okhttp3.ResponseBody以及void的响应体数据。当类型为ResponseBody时,还会判断接口方法是否含有@Streaming
注解,而后提供不一样的转换器实例。下面咱们就看下这三个数据转换器有什么区别吧
// BuiltInConverters
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 VoidResponseBodyConverter implements Converter<ResponseBody, Void> {
static final VoidResponseBodyConverter INSTANCE = new VoidResponseBodyConverter();
@Override
public Void convert(ResponseBody value) {
value.close();
return null;
}
}
复制代码
能够看到这三个转换器都实现了Converter接口的convert()
方法,这个方法会在后续处理响应数据时调用,如今咱们先看下这三个转换器的convert()
方法是如何实现的
@Streaming
注解适合在执行大文件下载任务的时候使用如今回到一开始的请求示例中,咱们定义的接口方法是这样的
public interface ExpressService {
@GET("query?type=ems&postid=11111111")
Call<ResponseBody> get();
}
复制代码
这里设置的响应数据类型是ResponseBody,即BuiltInConverters能够处理这个API方法,所以遍历查找转换器工厂的过程到了BuiltInConverters处就被拦截了下来,且因为该接口方法并无添加@Streaming
注解,因此最终HttpServiceMethod.createResponseConverter()
构建的响应数据转换器就是BufferingResponseBodyConverter
完成全部前置工做后,咱们回到Retrofit.create()
方法,由以前的分析可知API方法会被动态代理到
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
复制代码
而loadServiceMethod()
最终返回的是HttpServiceMethod的实例,所以咱们来看下HttpServiceMethod.invoke()
方法的代码
// HttpServiceMethod
@Override
ReturnT invoke(Object[] args) {
return callAdapter.adapt(new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}
复制代码
adapt()
方法的传参是OkHttpCall的实例,这是Retrofit层的请求执行器,其内部持有真实的请求执行器okhttp3.Call。OkHttpCall做为代理类主要负责Retrofit层与OkHttp层之间交互数据的转换
此外,从以前的讲解中咱们知道adapt()
方法的返回结果是ExecutorCallbackCall的实例,所以动态代理API方法最终获得的就是这个实例,其做为OkHttpCall的装饰器,主要负责协同回调执行器为OkHttpCall动态加强回调方面的功能
至此API方法的动态代理和加载配置的过程就分析完了,下一章咱们将分析Retrofit是如何发起请求以及处理响应数据的
这一章分析了加载API方法配置的过程,原理是利用动态代理机制,主要完成了如下工做:
本章咱们将分析请求与响应的过程,如下是对应的示例代码
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
复制代码
由上一章咱们知道,这里的call其实是装饰器ExecutorCallbackCall,咱们来看下ExecutorCallbackCall.enqueue()
方法的代码
// ExecutorCallAdapterFactory
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);
}
});
}
});
}
...
}
复制代码
ExecutorCallbackCall有两个成员变量,callbackExecutor与delegate,经过以前的分析咱们知道它们分别对应了MainThreadExecutor和OkHttpCall。那么先来分析MainThreadExecutor.execute()
方法,该方法在OkHttpCall的请求回调中被调用
// Platform.Android
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override
public void execute(Runnable r) {
handler.post(r);
}
}
复制代码
这里的功能很是好理解,综合以前的代码来看就是将OkHttpCall的请求回调结果发送至主线程。再来看OkHttpCall.enqueue()
方法
// OkHttpCall
@Override
public void enqueue(final Callback<T> callback) {
okhttp3.Call call;
call = rawCall = createRawCall();
...
call.enqueue(new okhttp3.Callback() {
@Override
public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response = parseResponse(rawResponse);
callback.onResponse(OkHttpCall.this, response);
...
}
@Override
public void onFailure(okhttp3.Call call, IOException e) {
callback.onFailure(OkHttpCall.this, e);
}
...
});
}
复制代码
这里我把核心的代码摘抄出来进行分析,首先是经过createRawCall()
方法获取真实的请求执行器
// OkHttpCall
private okhttp3.Call createRawCall() throws IOException {
okhttp3.Call call = callFactory.newCall(requestFactory.create(args));
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
复制代码
这里有两个须要关注的点,一是调用callFactory.newCall()
方法获取真实的请求执行器,callFactory实际上就是OkHttpClient对象的引用,这和咱们在OkHttp中生成请求执行器的方法一致;二是经过requestFactory.create()
方法获取请求体okhttp3.Request的实例,其中args是经过动态代理API方法拿到的传参。如今咱们开始分析生成Request对象的过程
// RequestFactory
okhttp3.Request create(Object[] args) throws IOException {
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args.length;
...
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl,
headers, contentType, hasBody, isFormEncoded, isMultipart);
List<Object> argumentList = new ArrayList<>(argumentCount);
for (int p = 0; p < argumentCount; p++) {
argumentList.add(args[p]);
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.get()
.tag(Invocation.class, new Invocation(method, argumentList))
.build();
}
复制代码
handlers是参数封装类ParameterHandler的集合,经过apply()
方法能够处理参数数据,转换成RequestBuilder须要的格式,而后经过RequestBuilder的引用设置数据,这些数据将在生成Request时用到。先来看下RequestBuilder的构造方法
// RequestBuilder
RequestBuilder(String method, HttpUrl baseUrl,
@Nullable String relativeUrl, @Nullable Headers headers, @Nullable MediaType contentType,
boolean hasBody, boolean isFormEncoded, boolean isMultipart) {
this.method = method;
this.baseUrl = baseUrl;
this.relativeUrl = relativeUrl;
this.requestBuilder = new Request.Builder();
this.contentType = contentType;
this.hasBody = hasBody;
if (headers != null) {
requestBuilder.headers(headers);
}
if (isFormEncoded) {
// Will be set to 'body' in 'build'.
formBuilder = new FormBody.Builder();
} else if (isMultipart) {
// Will be set to 'body' in 'build'.
multipartBuilder = new MultipartBody.Builder();
multipartBuilder.setType(MultipartBody.FORM);
}
}
复制代码
能够看到咱们以前在解析注解、加载API方法配置的过程当中生成的属性在这都获得了应用。再来看ParameterHandler.apply()
的过程,咱们以请求示例中定义的API方法为例,方法参数中使用了@Query
注解,对应的参数封装类是Query
// ParameterHandler
static final class Query<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
private final boolean encoded;
Query(String name, Converter<T, String> valueConverter, boolean encoded) {
this.name = checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
this.encoded = encoded;
}
@Override
void apply(RequestBuilder builder, @Nullable T value) throws IOException {
if (value == null) return; // Skip null values.
String queryValue = valueConverter.convert(value);
if (queryValue == null) return; // Skip converted but null values
builder.addQueryParam(name, queryValue, encoded);
}
}
复制代码
参数数据转换器在这里开始发挥做用了,能够经过调用Converter.convert()
方法将参数数据转换成RequestBuilder实际须要的数据,经过3.3.2一节的分析咱们知道处理String类型数据的转换器是ToStringConverter,所以这里valueConverter就是ToStringConverter实例的引用,从新回顾一下ToStringConverter.convert()
方法
// BuiltInConverters.ToStringConverter
@Override
public String convert(Object value) {
return value.toString();
}
复制代码
数据转换完毕后,继续调用RequestBuilder.addQueryParam()
方法设置Query参数的数据
// RequestBuilder
void addQueryParam(String name, @Nullable String value, boolean encoded) {
if (relativeUrl != null) {
// Do a one-time combination of the built relative URL and the base URL.
urlBuilder = baseUrl.newBuilder(relativeUrl);
...
relativeUrl = null;
}
if (encoded) {
//noinspection ConstantConditions Checked to be non-null by above 'if' block.
urlBuilder.addEncodedQueryParameter(name, value);
} else {
//noinspection ConstantConditions Checked to be non-null by above 'if' block.
urlBuilder.addQueryParameter(name, value);
}
}
复制代码
到这里就都是OkHttp构建Request的方法了,再也不展开细说。回到RequestFactory.create()
,继续往下看Request的构建过程
// RequestFactory.create
return requestBuilder.get()
.tag(Invocation.class, new Invocation(method, argumentList))
.build();
复制代码
首先调用了RequestBuilder.get()
方法,看下源码
Request.Builder get() {
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);
...
}
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);
}
复制代码
一样这里也都是OkHttp层的调用,成员变量requestBuilder对应的类型就是okhttp3.Request.Builder,调用build()
方法就能够生成Request对象了
至此OkHttpCall.createRawCall()
成功建立了一个okhttp3.Call的实例,如今咱们回到OkHttpCall.enqueue()
方法继续往下看
获得okhttp3.Call实例后,下一步就是调用Call.enqueue()
发起异步请求,并在回调中获得响应体对象okhttp3.Response,因为这是OkHttp层的,所以还须要解析转换成Retrofit层的响应体对象,解析转换的方法是OkHttpCall.parseResponse()
// OkHttpCall
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);
}
ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
try {
T body = responseConverter.convert(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;
}
}
复制代码
这里的重点是调用ResponseConverter.convert()
转换响应数据,以前分析过的内置和自定义的响应数据转换器在这发挥了做用,ResponseBody成功转换成用户须要的类型
至此咱们完成了okhttp3.Response的处理过程,下一步再将生成的retrofit2.Response对象经过回调方法返回给用户,请求与响应的过程以及整个Retrofit工做流程的源码分析就完成了
这一章分析了请求与响应的过程,主要完成了如下工做:
enqueue()
方法发起真实的异步请求最后以一张Retrofit的工做流程图总结以前的分析(ps:为了和流程进行区分,这里我将一些重要成员抽象成了数据源)