Retrofit2.0通過(guò)注解來(lái)配置請(qǐng)求的方式栗恩,比如請(qǐng)求的類型爷抓,Header盆赤,參數(shù)等等。通過(guò)動(dòng)態(tài)代理的方式來(lái)解釋注解客们。每一個(gè)參數(shù)注解都對(duì)應(yīng)著RequestBuilder的類型崇决,如何將注解標(biāo)注的參數(shù)和RequestBuilder的參數(shù)準(zhǔn)確的對(duì)應(yīng)起來(lái)就是由ParameterHandler來(lái)做的。
1.首先拿到所有方法參數(shù)的注解
方法參數(shù)的注解是按照你聲明的順序返回的
this.parameterAnnotationsArray = method.getParameterAnnotations();
2.每一個(gè)參數(shù)注解都對(duì)應(yīng)一種ParameterHandler
比如url和path 分別對(duì)應(yīng) ParameterHandler.RelativeUrl和ParameterHandler.Path類底挫,這兩個(gè)類負(fù)責(zé)給RequestBuilder的參數(shù)和注解標(biāo)識(shí)的方法的參數(shù)關(guān)聯(lián)起來(lái)
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());
并且將每一種參數(shù)注解對(duì)應(yīng)的ParameterHandler都保存在一個(gè)ParameterHandler數(shù)組中恒傻,這個(gè)數(shù)組中存儲(chǔ)數(shù)據(jù)的順序同樣也是參數(shù)聲明的順序。因?yàn)樽⒔饴暶鞯捻樞蚝蛥?shù)聲明的順序一致建邓,每次解析一個(gè)參數(shù)注解就創(chuàng)建一個(gè)ParameterHandler保存在數(shù)組中盈厘。
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
.....
.....
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
3.將參數(shù)和RequestBuilder關(guān)聯(lián)起來(lái)
ParameterHandler接口的定義以及一個(gè)子類。apply的目的就是將參數(shù)和RequestBuilder對(duì)應(yīng)起來(lái)
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方法將參數(shù)和RequestBuilder關(guān)聯(lián)起來(lái)
/**
* Builds an HTTP request from method arguments.
* 將請(qǐng)求的參數(shù)和保存的Handler一一對(duì)應(yīng)起來(lái)官边,參數(shù)順序和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和參數(shù)就依依對(duì)應(yīng)起來(lái)了
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}