注:当前分析的Retorfit版本为2.6.2
Retrofit初始化
一般使用retrofit的时候都是下面这段代码
public static final String API_URL = "https://api.github.com";
......
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
通过Retrofit
的内部类Builder
(builder模式)配置baseURL
(一般是所有网络Api地址的公共部分);配置转换器工厂ConverterFactory
(其作用是将网络请求的请求体requestBody和响应体responseBody做转换,比如GsonConverterFactory
创建的GsonRequestBodyConverter
将请求参数转换成MediaType为"application/json; charset=UTF-8"
的RequestBody,GsonResponseBodyConverter
则将OkHttp
网络请求的ResponseBody
通过Gson
反序列化成实体类);配置client
(默认采用OkHttp
);配置请求适配工厂CallAdapterFactory
(其作用是将Retrofit对象的create方法创建Call
类型转换成另一种类型,R一般为返回值的实体类类型。比如通过RxJava2CallAdapterFactory
创建的RxJava2CallAdapter
通过接口CallAdapter
的adapt
方法将Call
类型转换成io.reactivex.Observable
类型,);配置回调接口在那个线程执行callbackExecutor(Executor executor)
(即retrofit的回调方法retrofit2.Callback
,android默认是在主线程);配置callFactory callFactory(okhttp3.Call.Factory factory)
(即自定义call);配置validateEagerly(boolean validateEagerly)
用于是否在用Retrofit
的create
创建代理对象而不是在调用代理对象的方法的时候就开始校验Api接口中申明的所有方法时候合法。然后通过Builder
的build方法返回一个Retrofit
实例,重点关注一下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) {
//platform.defaultCallbackExecutor()返回的是MainThreadExecutor
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
//platform.defaultCallAdapterFactories()在SDK版本大于等于24的时候
//返回集合[CompletableFutureCallAdapterFactory,DefaultCallAdapterFactory]
//否则返回集合[DefaultCallAdapterFactory]
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List 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.
//内置BuiltInConverters,排在最前的符合要求converter会先用到,方式用户定义了一个一模一样的convert
converterFactories.add(new BuiltInConverters());
//用户配置的自定义Converter
converterFactories.addAll(this.converterFactories);
//platform.defaultConverterFactories()在SDK版本大于等于24返回OptionalConverterFactory,主要是针对java8的Optional否则返回空
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
可以看到就是配置参数给Retrofit
构造函数传值,下面进入代理对象创建环节。
创建接口的代理对象
注:例子引用了 samples
//实体类定义
public static class Contributor {
public final String login;
public final int contributions;
public Contributor(String login, int contributions) {
this.login = login;
this.contributions = contributions;
}
}
//接口定义
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
//关键点,创建代理对象
GitHub github = retrofit.create(GitHub.class);
//调用代理对象方法,如果没有在Retrofit的builder方法中配置
//.addCallAdapterFactory(RxJava2CallAdapterFactory.create())则返回的是Call
Call> call = github.contributors("square", "retrofit");
// 网络请求返回数据
List contributors = call.execute().body();
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
下面分析关键代码retrofit.create(GitHub.class)
,跟进去看一下,此处一些校验方法没有列出代码,注释了启作用
package retrofit2;
public final class Retrofit {
public T create(final Class service) {
//校验service类格式,service必须是接口类型,并且不能继承自其他接口
Utils.validateServiceInterface(service);
//Retrofit的builder类的validateEagerly方法配置,默认为false
if (validateEagerly) {
//主要是校验service类中所申明的方法不能是default方法(java 8中interface引入了default方法)
//同时不能是静态方法,如果满足要求,则调用loadServiceMethod方法
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.
//如果是调用的继承自Object方法(比如toString();hashCode(),wait(),notify,getClass())则普通调用,
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//如果是java8的默认方法
if (platform.isDefaultMethod(method)) {
//调用invokeDefaultMethod,实际实现是抛出UnsupportedOperationException异常
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//核心代码,API接口申明的那些方法
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
}
方法调用
通过上面的代码可以看到当调用接口API的方法实际上是通过动态代理回调方法里面调用的是ServiceMethod的invoke方法,先跟进ServiceMethod loadServiceMethod(Method method)
,看看是怎么查找的,后面我们再回来看ServiceMethod
的invoke(Object[] args)
方法的实现逻辑
package retrofit2;
abstract class ServiceMethod {
static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {
//生成RequestFactory的parseAnnotations方法会解析方法的注解,以及方法中的参数的注解,先跳过
RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);
Type returnType = method.getGenericReturnType();
//Utils.hasUnresolvableType方法判断Method的返回值类型不能是泛型,泛型数组,通配符,
//即类似于List,List[],List,List[](T为接口定义中的未指明具体类型参数)
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.");
}
//调用HttpServiceMethod的parseAnnotations,依然是解析接口方法上的注解,生成ServiceMethod
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
}
先列出Utils
类的hasUnresolvableType(@Nullable Type type)
方法逻辑分析,因为多处会用到它
package retrofit2;
final class Utils {
...
//判断是否不可解析类型
static boolean hasUnresolvableType(@Nullable Type type) {
//如果是不是泛型,可以解析
if (type instanceof Class) {
return false;
}
//如果是参数化类型,递归遍历里面具体的元素类型,比如List
接着分析RequestFactory.parseAnnotations(Retrofit retrofit, Method method)
代码逻辑
package retrofit2;
final class RequestFactory {
static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
return new Builder(retrofit, method).build();
}
...
}
貌似很简单,就是通过builder模式创建了一个RequestFactory
,跟进Builder的构造方法
static final class Builder {
final Retrofit retrofit;
final Method method;
final Annotation[] methodAnnotations;
final Annotation[][] parameterAnnotationsArray;
final Type[] parameterTypes;
//省略其他成员变量
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//获取标注在方法上的所有注解
this.methodAnnotations = method.getAnnotations();
//获取方法所有参数(带泛型)类型
this.parameterTypes = method.getGenericParameterTypes();
//获取方法所有参数的注解,注意是二维数组,因为每个参数可能会有多个注解修饰,而一个方法又可能有多个参数
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
}
可以看到构造方法中透传了Retrofit,要解析的Method,获取标注在方法上的所有注解,方法所有参数(带泛型)类型,参数的注解。注意Method的getParameterTypes()
和getGenericParameterTypes
区别在于,比如List
类型参数,前者通过Type的getTypeName
得到的是java.util.List
后者得到的是java.util.List
。接着跟进builder类的build
方法
package retrofit2;
final class RequestFactory {
//省略其他代码
RequestFactory build() {
//遍历修饰方法的注解,只解析Retrofit支持的那几个注解
for (Annotation annotation : methodAnnotations) {
//解析方法上的HTTP注解 ,后面分析
parseMethodAnnotation(annotation);
}
//没有找到Retrofit支持的那几个用于HTTP请求的注解,抛出异常
if (httpMethod == null) {
throw methodError(method, "HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
//如果不带请求体,只有PATCH,POST,PUT方法才带有请求体,说明不能在方法上用了@DELETE,@HEAD,@GET,@OPTIONS注解后又用@Multipart,@FormUrlEncoded注解
//具体规范参考HTTP协议
//hasBody,isMultipart,isFormEncoded的判断在上面的parseMethodAnnotation中完成
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).");
}
}
//针对带有注解的参数,创建对应的参数处理器ParameterHandler
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);
}
//relativeUrl ,gotUrl,gotField,gotPart的判断在parseParameter方法中完成
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);
}
//省略其他代码
}
总结一下就是build方法会去扫描api接口中方法的注解参数的注解,保证符合HTTP协议规范,同时保证方法注解中的占位符能和参数中注解中的对应的字段意义对应起来,能够拼接一个完成的URL请求,包括请求地址和请求参数。
接着分析parseMethodAnnotation(Annotation annotation)
方法
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(method = "DELETE", path = "remove/", hasBody = true)
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({"X-Foo: Bar","X-Ping: Pong"})
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
//@Multipart注解不能重复使用
if (isFormEncoded) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
//@FormUrlEncoded注解不能重复使用
if (isMultipart) {
throw methodError(method, "Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
可以看到对@DELETE
,@GET
,@HEAD
,@PATCH
,@POST
,@PUT
,@OPTIONS
均是调用了parseHttpMethodAndPath
方法,如下所示
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
//只能有一个HTTP方法
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.
// 针对形如 aaa/bbb?key1={key1}&key2={key2}的URL处理
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);//通过正则表达式获取相对地址中{}包含的参数
}
针对@Headers
注解,则是parseHeaders
方法,如下所示,比较简单,获取数组列表,然后对每一个元素用:
拆分为两部分,前者为键,后者为值然后生成headers
private Headers parseHeaders(String[] headers) {
Headers.Builder builder = new Headers.Builder();
for (String header : headers) {
int colon = header.indexOf(':');
if (colon == -1 || colon == 0 || colon == header.length() - 1) {
throw methodError(method,
"@Headers value must be in the form \"Name: Value\". Found: \"%s\"", header);
}
String headerName = header.substring(0, colon);
String headerValue = header.substring(colon + 1).trim();
if ("Content-Type".equalsIgnoreCase(headerName)) {
try {
contentType = MediaType.get(headerValue);
} catch (IllegalArgumentException e) {
throw methodError(method, e, "Malformed content type: %s", headerValue);
}
} else {
builder.add(headerName, headerValue);
}
}
return builder.build();
}
接着分析
parseParameter( int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation)
方法:
private @Nullable ParameterHandler parseParameter(
int p, Type parameterType, @Nullable Annotation[] annotations, boolean allowContinuation) {
ParameterHandler result = null;
if (annotations != null) {
for (Annotation annotation : annotations) {
//通过parseParameterAnnotation来获取对应的ParameterHandler
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;
}
}
if (result == null) {
//当为最后一个参数的时候allowContinuation为true
if (allowContinuation) {
try {
//Continuation.class是Kotlin协程模块中kotlin.coroutines.Continuation;
//有关协程请参考https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html
if (Utils.getRawType(parameterType) == Continuation.class) {
isKotlinSuspendFunction = true;
return null;
}
} catch (NoClassDefFoundError ignored) {
}
}
throw parameterError(method, p, "No Retrofit annotation found.");
}
return result;
}
实际上还是调用的是ParameterHandler parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation)
方法。由于这个方法比较长,但是做的事情还是很清楚的,就是根据api接口中申明的参数注解类型生成相应的ParameterHandler
,同时参数不能为不可解析类型,就是前文的hasUnresolvableType(@Nullable Type type)
的逻辑。未落不冲谈主题且限于篇幅,此处只是列出该方法的几个最外层的条件分支,根据不同的注解@Url
,@Path
,@Query
,@QueryName
,@QueryMap
,@Header
,@HeaderMap
,@Feild
,@FieldMap
,@Part
,@PartMap
,@Body
,@Tag
,生成相应的ParameterHandler。
private ParameterHandler parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
if (annotation instanceof Url) { //如果是@Url注解,返回ParameterHandler.RelativeUrl
//省略一堆逻辑
。。。
if (type == HttpUrl.class
|| type == String.class
|| type == URI.class
|| (type instanceof Class && "android.net.Uri".equals(((Class) type).getName()))) {
return new ParameterHandler.RelativeUrl(method, p);
} else {
throw parameterError(method, p,
"@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
}
} else if (annotation instanceof Path) { //如果是@Path注解,返回ParameterHandler.Path
//省略一堆逻辑
。。。
Converter converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Path<>(method, p, name, converter, path.encoded());
} else if (annotation instanceof Query) { //如果是@Query注解,返回ParameterHandler.Query
validateResolvableType(p, type);
Query query = (Query) annotation;
String name = query.value();
boolean encoded = query.encoded();
Class rawParameterType = Utils.getRawType(type);
gotQuery = true;
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ ")");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
Class arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter converter =
retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).array();
} else {
Converter converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.Query<>(name, converter, encoded);
}
} else if (annotation instanceof QueryName) {//如果是@QueryName 注解,返回ParameterHandler.QueryName
validateResolvableType(p, type);
QueryName query = (QueryName) annotation;
boolean encoded = query.encoded();
Class rawParameterType = Utils.getRawType(type);
gotQueryName = true;
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ ")");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.QueryName<>(converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
Class arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter converter =
retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.QueryName<>(converter, encoded).array();
} else {
Converter converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.QueryName<>(converter, encoded);
}
} else if (annotation instanceof QueryMap) { //如果是@QueryMap 注解,返回ParameterHandler.QueryMap
//省略一堆逻辑
。。。。
return new ParameterHandler.QueryMap<>(method, p,
valueConverter, ((QueryMap) annotation).encoded());
} else if (annotation instanceof Header) { //如果是@Header 注解,返回ParameterHandler.Header
validateResolvableType(p, type);
Header header = (Header) annotation;
String name = header.value();
Class rawParameterType = Utils.getRawType(type);
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(method, p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ ")");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Header<>(name, converter).iterable();
} else if (rawParameterType.isArray()) {
Class arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter converter =
retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Header<>(name, converter).array();
} else {
Converter converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.Header<>(name, converter);
}
} else if (annotation instanceof HeaderMap) {//如果是@HeaderMap 注解,返回ParameterHandler.Headers或者ParameterHandler.HeaderMap
if (type == Headers.class) {
return new ParameterHandler.Headers(method, p);//返回ParameterHandler.Headers
}
//省略一堆逻辑
。。。。
return new ParameterHandler.HeaderMap<>(method, p, valueConverter); //返回ParameterHandler.HeaderMap
} else if (annotation instanceof Field) {//如果是@Field 注解,返回ParameterHandler.Field
//省略一堆逻辑
。。。。
Class rawParameterType = Utils.getRawType(type);
if (Iterable.class.isAssignableFrom(rawParameterType)) {
//省略一堆逻辑
。。。。
return new ParameterHandler.Field<>(name, converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
//省略一堆逻辑
。。。。
return new ParameterHandler.Field<>(name, converter, encoded).array();
} else {
//省略一堆逻辑
。。。。
return new ParameterHandler.Field<>(name, converter, encoded);
}
} else if (annotation instanceof FieldMap) { //如果是@FieldMap 注解,返回ParameterHandler.Field
//省略一堆逻辑
。。。。
return new ParameterHandler.FieldMap<>(method, p,
valueConverter, ((FieldMap) annotation).encoded());
} else if (annotation instanceof Part) { //如果是@Part 注解,根据具体情况返回ParameterHandler.RawPart或者ParameterHandler.Part
validateResolvableType(p, type);
if (!isMultipart) {
throw parameterError(method, p,
"@Part parameters can only be used with multipart encoding.");
}
Part part = (Part) annotation;
gotPart = true;
String partName = part.value();
Class rawParameterType = Utils.getRawType(type);
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 {
throw parameterError(method, p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
}
} else {
Headers headers =
Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
"Content-Transfer-Encoding", part.encoding());
if (Iterable.class.isAssignableFrom(rawParameterType)) {
//省略一堆逻辑
。。。
return new ParameterHandler.Part<>(method, p, headers, converter).iterable();
} else if (rawParameterType.isArray()) {
//省略一堆逻辑
。。。
return new ParameterHandler.Part<>(method, p, headers, converter).array();
} else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
throw parameterError(method, p,
"@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
} else {
Converter converter =
retrofit.requestBodyConverter(type, annotations, methodAnnotations);
return new ParameterHandler.Part<>(method, p, headers, converter);
}
}
} else if (annotation instanceof PartMap) { //如果是@PartMap 注解,返回ParameterHandler.PartMap
//省略一堆逻辑
。。。。
return new ParameterHandler.PartMap<>(method, p, valueConverter, partMap.encoding());
} else if (annotation instanceof Body) { //如果是@Body 注解,返回ParameterHandler.Body
//省略一堆逻辑
。。。。
return new ParameterHandler.Body<>(method, p, converter);
} else if (annotation instanceof Tag) { //如果是@Tag 注解,返回ParameterHandler.Tag
//省略一堆逻辑
。。。。
return new ParameterHandler.Tag<>(tagType);
}
return null; // Not a Retrofit annotation.
}
所有的根据注解生成具体的ParameterHandler都是继承自ParameterHandler,在生成真正的okhttp3.Request
请求的时候是会调用复写ParameterHandler
的apply(RequestBuilder builder, @Nullable T value)
方法,以实现生成符合http规范的请求头,请求参数,请求体。后文会继续分析apply
调用的时机。
回到前文ServiceMethod的parseAnnotations
方法,如下所示,我们已经大体分析了 RequestFactory
的parseAnnotations()
方法,现在分析 HttpServiceMethod
的parseAnnotations()
方法。
static ServiceMethod 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);
}
跟进HttpServiceMethod
的parseAnnotations(retrofit, method, requestFactory)
去看一下
static HttpServiceMethod parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
if (isKotlinSuspendFunction) {//是否是Kotlin的suspend方法,因为我们定义在API接口GitHub里面的方法不是suspend,此处为false
Type[] parameterTypes = method.getGenericParameterTypes();
Type responseType = Utils.getParameterLowerBound(0,
(ParameterizedType) parameterTypes[parameterTypes.length - 1]);
if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
// Unwrap the actual body type from Response.
responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
continuationWantsResponse = true;
} else {
// TODO figure out if type is nullable or not
// Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
// Find the entry for method
// Determine if return type is nullable or not
}
adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
} else {
adapterType = method.getGenericReturnType();//方法的返回类型
}
//重点1,找到对应的callAdapter
CallAdapter callAdapter =
createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
if (responseType == okhttp3.Response.class) {
throw methodError(method, "'"
+ getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
if (responseType == Response.class) {
throw methodError(method, "Response must include generic type (e.g., Response)");
}
// TODO support Unit for Kotlin?
if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
throw methodError(method, "HEAD method must use Void as response type.");
}
//重点2,找到对应的Converter
Converter responseConverter =
createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
if (!isKotlinSuspendFunction) {
//重点3,我们用到是CallAdapted
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
} else if (continuationWantsResponse) {
//针对kotlin的非suspend方法
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod) new SuspendForResponse<>(requestFactory,
callFactory, responseConverter, (CallAdapter>) callAdapter);
} else {//针对kotlin的suspend方法
//noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
return (HttpServiceMethod) new SuspendForBody<>(requestFactory,
callFactory, responseConverter, (CallAdapter>) callAdapter,
continuationBodyNullable);
}
}
}
进入createCallAdapter
方法看看逻辑
private static CallAdapter createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
try {
//noinspection unchecked
return (CallAdapter) 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
的callAdapter
方法,进去看一下,分析逻辑见注释。
public CallAdapter nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
//callAdapter传入的skipPast为null,因此callAdapterFactories.indexOf(skipPast)的值为-1,因此start为0
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
//返回的是callAdapterFactories里面符合要要求的CallAdapter,前面的Retrofit的Builder在builder函数中
//默认添加了[CompletableFutureCallAdapterFactory,DefaultCallAdapterFactory]或者[DefaultCallAdapterFactory]
//如果用户不添加其他的CallAdapterFactory的话,我们在Github的API中返回值的类型是Call> ,returnType是Call.class类型的,
//DefaultCallAdapterFactory恰好是针对Call.class,CompletableFutureCallAdapterFactory是针对CompletableFuture.class,
//因此拿到的是DefaultCallAdapterFactory,返回的是DefaultCallAdapterFactory,生成的
CallAdapter adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
通过上面分析可以知道,得到的是DefaultCallAdapterFactory通过get( Type returnType, Annotation[] annotations, Retrofit retrofit)
方法拿到的CallAdapter,我们进入看一下
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Executor callbackExecutor;
DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
this.callbackExecutor = callbackExecutor;
}
@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");
}
//返回形如Call或者 Call中Foo的类型
final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);
final Executor executor = Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
? null
: callbackExecutor;
//此处创建了一个CallAdapter
return new CallAdapter