Retrofit2.0通过注解来配置请求的方式,比如请求的类型,Header,参数等等。通过动态代理的方式来解释注解。每一个参数注解都对应着RequestBuilder的类型,如何将注解标注的参数和RequestBuilder的参数准确的对应起来就是由ParameterHandler来做的。
1.首先拿到所有方法参数的注解
方法参数的注解是按照你声明的顺序返回的
this.parameterAnnotationsArray = method.getParameterAnnotations();
2.每一个参数注解都对应一种ParameterHandler
比如url和path 分别对应 ParameterHandler.RelativeUrl和ParameterHandler.Path类,这两个类负责给RequestBuilder的参数和注解标识的方法的参数关联起来
if (annotation instanceof Url) {
......
if (type == HttpUrl.class
|| type == String.class
|| type == URI.class
|| (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
return new ParameterHandler.RelativeUrl();
} else {
throw parameterError(p,
"@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
}
} else if (annotation instanceof Path) {
......
Path path = (Path) annotation;
String name = path.value();
validatePathName(p, name);
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
return new ParameterHandler.Path<>(name, converter, path.encoded());
并且将每一种参数注解对应的ParameterHandler都保存在一个ParameterHandler数组中,这个数组中存储数据的顺序同样也是参数声明的顺序。因为注解声明的顺序和参数声明的顺序一致,每次解析一个参数注解就创建一个ParameterHandler保存在数组中。
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
.....
.....
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
3.将参数和RequestBuilder关联起来
ParameterHandler接口的定义以及一个子类。apply的目的就是将参数和RequestBuilder对应起来
abstract class ParameterHandler<T> {
abstract void apply(RequestBuilder builder, T value) throws IOException;
static final class Header<T> extends ParameterHandler<T> {
private final String name;
private final Converter<T, String> valueConverter;
Header(String name, Converter<T, String> valueConverter) {
this.name = checkNotNull(name, "name == null");
this.valueConverter = valueConverter;
}
@Override
void apply(RequestBuilder builder, T value) throws IOException {
if (value == null) return; // Skip null values.
builder.addHeader(name, valueConverter.convert(value));
}
}
.....
}
ServiceMethod的toRequest方法将参数和RequestBuilder关联起来
/**
* Builds an HTTP request from method arguments.
* 将请求的参数和保存的Handler一一对应起来,参数顺序和handler的保存顺序是一致的
*/
Request toRequest(Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
......
for (int p = 0; p < argumentCount; p++) {
//这里requestbuilder和参数就依依对应起来了
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}