在第一章節(jié)講到了ServiceMethod的toRequest()方法誓琼,下面就從toRequest()方法方法開(kāi)始分析ServiceMethod,toRequest()的源碼如下:
Request toRequest(Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);//這里是參數(shù)參數(shù)配置的核心
}
return requestBuilder.build();
}
先來(lái)看一下handlers(也就是parameterHandlers)這個(gè)屬性的功能。parameterHandlers的初始化在ServiceMethod的內(nèi)部類(lèi)Builder的build()方法中初始化。build()方法如下:
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
int parameterCount = parameterAnnotationsArray.length;//方法的參數(shù)的所有注解
parameterHandlers = new ParameterHandler<?>[parameterCount];//初始化
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {//參數(shù)類(lèi)型檢查
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.");
}
//保存了參數(shù)類(lèi)型和參數(shù)的注解
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
這里先補(bǔ)充一點(diǎn)反射的知識(shí)。
Annotation[] annotations = method.getAnnotations();//獲取方法的所有注解
Annotation[][] annos = method.getParameterAnnotations();//獲取方法的參數(shù)的所有注解郁竟。
Type[] t = m.getGenericParameterTypes();//返回方法的參數(shù)列表
Utils.hasUnresolvableType()這個(gè)方法的源碼如下:
static boolean hasUnresolvableType(Type type) {
if (type instanceof Class<?>) {
return false;
}
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
for (Type typeArgument : parameterizedType.getActualTypeArguments()) {
if (hasUnresolvableType(typeArgument)) {
return true;
}
}
return false;
}
if (type instanceof GenericArrayType) {
return hasUnresolvableType(((GenericArrayType) type).getGenericComponentType());
}
if (type instanceof TypeVariable) {
return true;
}
if (type instanceof WildcardType) {
return true;
}
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <" + type + "> is of type " + className);
}
hasUnresolvableType()其實(shí)就是做了參數(shù)的類(lèi)型檢查。具體各個(gè)類(lèi)型代表的含義由境,可以百度反射相關(guān)知識(shí)棚亩。
parseParameter()方法源碼如下:
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
ParameterHandler<?> result = null;
for (Annotation annotation : annotations) {
ParameterHandler<?> annotationAction = parseParameterAnnotation(
p, parameterType, annotations, annotation);
if (annotationAction == null) {
continue;
}
if (result != null) {
throw parameterError(p, "Multiple Retrofit annotations found, only one allowed.");
}
result = annotationAction;
}
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
接著看parseParameterAnnotation()的源碼:
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
//如果注解是Url
if (annotation instanceof Url) {
if (gotUrl) {
throw parameterError(p, "Multiple @Url method annotations found.");
}
if (gotPath) {
throw parameterError(p, "@Path parameters may not be used with @Url.");
}
if (gotQuery) {
throw parameterError(p, "A @Url parameter must not come after a @Query");
}
if (relativeUrl != null) {
throw parameterError(p, "@Url cannot be used with @%s URL", httpMethod);
}
gotUrl = true;
if (type == HttpUrl.class
|| type == String.class
|| type == URI.class
|| (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
return new ParameterHandler.RelativeUrl();//如果沒(méi)有異常蓖议,返回Url對(duì)應(yīng)的ParameterHandler。
} else {
throw parameterError(p,
"@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
}
} else if (annotation instanceof Path) {
if (gotQuery) {
throw parameterError(p, "A @Path parameter must not come after a @Query.");
}
if (gotUrl) {
throw parameterError(p, "@Path parameters may not be used with @Url.");
}
if (relativeUrl == null) {
throw parameterError(p, "@Path can only be used with relative url on @%s", httpMethod);
}
gotPath = true;
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());
}
……
}
RelativeUrl類(lèi)的定義如下(其他的注解定義和使用方式都差不多讥蟆,就不一一說(shuō)明):
static final class RelativeUrl extends ParameterHandler<Object> {
@Override void apply(RequestBuilder builder, Object value) {
builder.setRelativeUrl(value);
}
}
RequestBuilder的setRelativeUrl()方法定義如下:
void setRelativeUrl(Object relativeUrl) {
//url不能為空
if (relativeUrl == null) throw new NullPointerException("@Url parameter is null.");
this.relativeUrl = relativeUrl.toString();
}
關(guān)于parameterHandlers就介紹到這里勒虾,總結(jié)起來(lái)就是parameterHandlers里面存放的是類(lèi)似于RelativeUrl這樣的類(lèi),專(zhuān)門(mén)用于處理各種注解瘸彤。ServiceMethod的toRequest()方法修然,都會(huì)調(diào)用parameterHandlers里面的ParameterHandler的apply()方法。調(diào)用完之后质况,所有的參數(shù)都填入到RequestBuilder中去了愕宋。到此,Retrofit就完成了數(shù)據(jù)的收集功能结榄。