整體Retrofit內(nèi)容如下:
- 1、Retrofit解析1之前哨站——理解RESTful
- 2庆亡、Retrofit解析2之使用簡(jiǎn)介
- 3、Retrofit解析3之反射
- 4拗引、Retrofit解析4之注解
- 5点把、Retrofit解析5之代理設(shè)計(jì)模式
- 6橘荠、Retrofit解析6之面向接口編程
- 7、Retrofit解析7之相關(guān)類解析
- 8郎逃、Retrofit解析8之核心解析——ServiceMethod及注解1
- 9哥童、Retrofit解析8之核心解析——ServiceMethod及注解2
- 10、Retrofit解析9之流程解析
- 11褒翰、Retrofit解析10之感謝
由于簡(jiǎn)述篇幅的限制贮懈,接上一篇文章繼續(xù)
3.2.8压恒、 Builder的方法parseParameter解析
看名字這個(gè)方法我們理解為解析參數(shù)的方法
private ParameterHandler<?> parseParameter(
int p, Type parameterType, Annotation[] annotations) {
// 定義一個(gè)ParameterHandler 變量
ParameterHandler<?> result = null;
//parseParameterAnnotation方法來獲取對(duì)應(yīng)的ParameterHandler對(duì)象
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.");
}
//對(duì)之前定義的變量賦值
result = annotationAction;
}
//非空檢查
if (result == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
return result;
}
這個(gè)方法內(nèi)部很簡(jiǎn)單,主要就是通過遍歷annotations错邦,內(nèi)部調(diào)用parseParameterAnnotation來獲取ParameterHandler對(duì)象并返回探赫。
那讓我們來看看parseParameterAnnotation()方法里面是怎么調(diào)用的
3.2.9、 Builder的方法parseParameterAnnotation解析
private ParameterHandler<?> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
//如果注解是 @Url
if (annotation instanceof Url) {
//默認(rèn)是在這里給gotUrl賦值的撬呢,且只能賦值一次伦吠,如果gotUrl==true,則說明之前賦值過魂拦,拋異常
if (gotUrl) {
throw parameterError(p, "Multiple @Url method annotations found.");
}
//@Url 注解和@Path 是互斥的毛仪,所以不能并存,發(fā)現(xiàn)并存則拋異常
if (gotPath) {
throw parameterError(p, "@Path parameters may not be used with @Url.");
}
//如果已經(jīng)使用了@Query芯勘、@QueryMap或者@QueryName箱靴,會(huì)出問題,因?yàn)閼?yīng)該先使用@Url 后才能配置Query等的注解
if (gotQuery) {
throw parameterError(p, "A @Url parameter must not come after a @Query");
}
//如果設(shè)置了relativeUrl荷愕,說明已經(jīng)動(dòng)態(tài)配置過url衡怀,所以這時(shí)候不能再使用@Url 注解
if (relativeUrl != null) {
throw parameterError(p, "@Url cannot be used with @%s URL", httpMethod);
}
//給gotUrl賦值為true
gotUrl = true;
//類型判斷
if (type == HttpUrl.class
|| type == String.class
|| type == URI.class
|| (type instanceof Class && "android.net.Uri".equals(((Class<?>) type).getName()))) {
//返回ParameterHandler的靜態(tài)內(nèi)部類RelativeUrl
return new ParameterHandler.RelativeUrl();
//至此解析@Url 完畢
} else {
throw parameterError(p,
"@Url must be okhttp3.HttpUrl, String, java.net.URI, or android.net.Uri type.");
}
//如果是@ Path 注解
} else if (annotation instanceof Path) {
//如果已經(jīng)設(shè)置了gotQuery,說明之前解析過@Query、@QueryMap或者@QueryName安疗,這會(huì)導(dǎo)致動(dòng)態(tài)配置的異常抛杨,所以拋異常
if (gotQuery) {
throw parameterError(p, "A @Path parameter must not come after a @Query.");
}
//上面解釋過,@Path和@Url是互斥的
if (gotUrl) {
throw parameterError(p, "@Path parameters may not be used with @Url.");
}
//如果設(shè)置了relativeUrl為null荐类,無法進(jìn)行動(dòng)態(tài)配置怖现,所以會(huì)拋異常
if (relativeUrl == null) {
throw parameterError(p, "@Path can only be used with relative url on @%s", httpMethod);
}
//給gotPath賦值
gotPath = true;
//獲取Path對(duì)象
Path path = (Path) annotation;
String name = path.value();
//通過正則表達(dá)式檢查是否符合要求
validatePathName(p, name);
//調(diào)用retrofit的stringConverter來獲取一個(gè)轉(zhuǎn)換器,通過泛型我們知道這個(gè)轉(zhuǎn)化器的輸出是String
Converter<?, String> converter = retrofit.stringConverter(type, annotations);
//返回ParameterHandler的靜態(tài)內(nèi)部類Path對(duì)象
return new ParameterHandler.Path<>(name, converter, path.encoded());
//至此解析@Path結(jié)束
//如果是@Query 注解
} else if (annotation instanceof Query) {
//類型轉(zhuǎn)化玉罐,獲取對(duì)應(yīng)的值
Query query = (Query) annotation;
String name = query.value();
boolean encoded = query.encoded();
//獲取真實(shí)的類型
Class<?> rawParameterType = Utils.getRawType(type);
//給gotQuery賦值屈嗤,說明已經(jīng)使用了 注解
gotQuery = true;
//如果rawParameterType是Iterable接口的子類
if (Iterable.class.isAssignableFrom(rawParameterType)) {
//如果不是參數(shù)化的類型,則拋出異常
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
}
//如果是參數(shù)化的類型吊输,則進(jìn)行強(qiáng)制類型轉(zhuǎn)化
ParameterizedType parameterizedType = (ParameterizedType) type;
//獲取第一個(gè)入?yún)⒌膮?shù)類型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
//獲取輸出類型是String的轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(iterableType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Query饶号,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象
return new ParameterHandler.Query<>(name, converter, encoded).iterable();
//如果類型是數(shù)組類型的
} else if (rawParameterType.isArray()) {
//如果是基本基本類型則需要裝箱操作
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
//獲取輸出類型是String的轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Query,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象璧亚。
return new ParameterHandler.Query<>(name, converter, encoded).array();
} else {
//如果既不是集合也不是數(shù)組類型讨韭,則是普通類型
//獲取輸出類型的是String的類型轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(type, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Query
return new ParameterHandler.Query<>(name, converter, encoded);
}
//自此 解析@Query 完畢
//如果是 @QueryName 注解
} else if (annotation instanceof QueryName) {
//獲取QueryName 注解的值
QueryName query = (QueryName) annotation;
boolean encoded = query.encoded();
//獲取原始類型
Class<?> rawParameterType = Utils.getRawType(type);
gotQuery = true;
//如果rawParameterType是Iterable接口的子類
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
}
//如果是參數(shù)化的類型,則進(jìn)行強(qiáng)制類型轉(zhuǎn)化
ParameterizedType parameterizedType = (ParameterizedType) type;
//獲取第一個(gè)入?yún)⒌膮?shù)類型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
//獲取輸出類型是String的轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(iterableType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryName癣蟋,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象透硝。
return new ParameterHandler.QueryName<>(converter, encoded).iterable();
//如果類型是數(shù)組類型的
} else if (rawParameterType.isArray()) {
//如果是基本基本類型則需要裝箱操作
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
//獲取輸出類型是String的轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryName,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象疯搅。
return new ParameterHandler.QueryName<>(converter, encoded).array();
} else {
//如果既不是集合也不是數(shù)組類型濒生,則是普通類型
//獲取輸出類型的是String的類型轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(type, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryName
return new ParameterHandler.QueryName<>(converter, encoded);
}
//如果是 @QueryMap 注解,
} else if (annotation instanceof QueryMap) {
//獲取原始的類型
Class<?> rawParameterType = Utils.getRawType(type);
//如果不是Map的接口的子類幔欧,拋異常
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@QueryMap parameter type must be Map.");
}
//獲取類型的超類
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
//如果不是參數(shù)類型罪治,則拋異常
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p, "Map must include generic types (e.g., Map<String, String>)");
}
//強(qiáng)制類型轉(zhuǎn)化
ParameterizedType parameterizedType = (ParameterizedType) mapType;
//獲取第一個(gè)入?yún)⒌膮?shù)類型丽声,其實(shí)就是map中key的類型,一般是String
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
//如果不是String 類型觉义,則拋異常
if (String.class != keyType) {
throw parameterError(p, "@QueryMap keys must be of type String: " + keyType);
}
//獲取第二個(gè)參數(shù)的類型,也就是value的值
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
//獲取輸出是String的轉(zhuǎn)化器
Converter<?, String> valueConverter =
retrofit.stringConverter(valueType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類QueryMap雁社,并返回
return new ParameterHandler.QueryMap<>(valueConverter, ((QueryMap) annotation).encoded());
//如果是@Header 注解
} else if (annotation instanceof Header) {
//獲取header的值
Header header = (Header) annotation;
String name = header.value();
//獲取原始類型
Class<?> rawParameterType = Utils.getRawType(type);
//如果是Iterable的子類
if (Iterable.class.isAssignableFrom(rawParameterType)) {
//參數(shù)類型判斷
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
//獲取第一個(gè)參數(shù)的類型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
//獲取輸出是String 類型的轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(iterableType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Header,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象
return new ParameterHandler.Header<>(name, converter).iterable();
//如果是數(shù)組類型
} else if (rawParameterType.isArray()) {
//裝箱操作
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
//獲取輸出為String 類型的 轉(zhuǎn)換器
Converter<?, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Header晒骇,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象霉撵。
return new ParameterHandler.Header<>(name, converter).array();
} else {
//如果既不是迭代器也不是數(shù)組,則是普通類型
//獲取輸出為String 類型的 轉(zhuǎn)換器
Converter<?, String> converter =
retrofit.stringConverter(type, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Header
return new ParameterHandler.Header<>(name, converter);
}
//如果是@HeaderMap 注解
} else if (annotation instanceof HeaderMap) {
//獲取參數(shù)的原始類型
Class<?> rawParameterType = Utils.getRawType(type);
//如果不是Map接口類型的子類洪囤,則拋異常
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@HeaderMap parameter type must be Map.");
}
//獲取類型的超類
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
//參數(shù)類型判斷
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p, "Map must include generic types (e.g., Map<String, String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) mapType;
//獲取第一個(gè)參數(shù)的類型徒坡,是key的類型
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
//key值 一定是String的,不是String 則拋異常
if (String.class != keyType) {
throw parameterError(p, "@HeaderMap keys must be of type String: " + keyType);
}
//獲取value的類型
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
//獲取輸出是 String的轉(zhuǎn)化器
Converter<?, String> valueConverter =
retrofit.stringConverter(valueType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類HeaderMap
return new ParameterHandler.HeaderMap<>(valueConverter);
// 如果是 @Field
} else if (annotation instanceof Field) {
// 如果沒有使用方法注解 @isFormEncoded瘤缩,卻使用參數(shù)注解@Field喇完,則拋出異常
if (!isFormEncoded) {
throw parameterError(p, "@Field parameters can only be used with form encoding.");
}
// 獲取 注解的內(nèi)容
Field field = (Field) annotation;
String name = field.value();
boolean encoded = field.encoded();
// 給gotField賦值
gotField = true;
//獲取原始類型
Class<?> rawParameterType = Utils.getRawType(type);
// 如果是Iterable類的子類
if (Iterable.class.isAssignableFrom(rawParameterType)) {
// 參數(shù)類型判斷
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
// 獲取第一個(gè)參數(shù)的類型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
//獲取 輸出是String類型的 轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(iterableType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Field,然后調(diào)用iterable()方法 獲取一個(gè)新的ParameterHandler對(duì)象
return new ParameterHandler.Field<>(name, converter, encoded).iterable();
//如果是 數(shù)組類型
} else if (rawParameterType.isArray()) {
//裝箱操作
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
//獲取輸出是String的 轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Field剥啤,然后調(diào)用array()方法 獲取一個(gè)新的ParameterHandler對(duì)象锦溪。
return new ParameterHandler.Field<>(name, converter, encoded).array();
} else {
// 如果既不是集合也不是數(shù)組類型,則是普通類型
//獲取 輸出是String類型轉(zhuǎn)化器
Converter<?, String> converter =
retrofit.stringConverter(type, annotations);
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Field
return new ParameterHandler.Field<>(name, converter, encoded);
}
//如果@注解 是FieldMap
} else if (annotation instanceof FieldMap) {
//如果不是表單提交則拋異常
if (!isFormEncoded) {
throw parameterError(p, "@FieldMap parameters can only be used with form encoding.");
}
//獲取原始類型
Class<?> rawParameterType = Utils.getRawType(type);
// 如果不是Map接口 铐殃,拋 異常
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@FieldMap parameter type must be Map.");
}
// 獲取 類型的 超類
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
// 參數(shù)類型判斷
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p,
"Map must include generic types (e.g., Map<String, String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) mapType;
// 獲取key的 類型
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
// key值一定是String
if (String.class != keyType) {
throw parameterError(p, "@FieldMap keys must be of type String: " + keyType);
}
// 獲取value的 類型
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
// 獲取 輸出類型是String的轉(zhuǎn)化器
Converter<?, String> valueConverter =
retrofit.stringConverter(valueType, annotations);
//給 gotField 賦值
gotField = true;
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類FieldMap海洼。
return new ParameterHandler.FieldMap<>(valueConverter, ((FieldMap) annotation).encoded());
// 如果 是@ Part 注解
} else if (annotation instanceof Part) {
//如果沒有使用@isMultipart 注解則拋異常
if (!isMultipart) {
throw parameterError(p, "@Part parameters can only be used with multipart encoding.");
}
//獲取 @Part 注解的值
Part part = (Part) annotation;
gotPart = true;
String partName = part.value();
//獲取原始類型
Class<?> rawParameterType = Utils.getRawType(type);
//如果 partName 是空的
if (partName.isEmpty()) {
// 類型是Iterable接口的子類
if (Iterable.class.isAssignableFrom(rawParameterType)) {
// 如果不是參數(shù)類型,則拋異常
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
// 獲取第一個(gè)參數(shù)的類型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
//如果原始類型不是MultipartBody.Part的子類富腊,則拋異常
if (!MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) {
throw parameterError(p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
}
// 返回ParameterHandler內(nèi)部類RawPart.INSTANCE的iterable()方法
return ParameterHandler.RawPart.INSTANCE.iterable();
//如果是數(shù)組類型
} else if (rawParameterType.isArray()) {
// 獲取類的組件類型的數(shù)組
Class<?> arrayComponentType = rawParameterType.getComponentType();
//如果不是Part類子類,則拋異常
if (!MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
throw parameterError(p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
}
// 返回ParameterHandler內(nèi)部類RawPart.INSTANCE的array()方法
return ParameterHandler.RawPart.INSTANCE.array();
//如果是MultipartBody.Part的子類
} else if
(MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
return ParameterHandler.RawPart.INSTANCE;
} else {
throw parameterError(p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
}
//partName不為空
} else {
//定義Header
Headers headers =
Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
"Content-Transfer-Encoding", part.encoding());
//如果類型是Iterable的子類
if (Iterable.class.isAssignableFrom(rawParameterType)) {
//參數(shù)類型判斷
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "<String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
//獲取 第一個(gè)參數(shù)的類型
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
//使用@Part 注解且注解內(nèi)部有值域帐,則不能和MultipartBody.Part一起使用赘被,例如:@Part("description") RequestBody description是可以的,@Part MultipartBody.Part file也是可以的肖揣,但是@Partt("file") MultipartBody.Part file 是不可以的民假。
if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) {
throw parameterError(p, "@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
}
//獲取輸出是RequestBody的轉(zhuǎn)化器
Converter<?, RequestBody> converter =
retrofit.requestBodyConverter(iterableType, annotations, methodAnnotations);
// 返回ParameterHandler內(nèi)部類Part的實(shí)例,然后調(diào)用的iterable()方法返回一個(gè)ParameterHandler對(duì)象
return new ParameterHandler.Part<>(headers, converter).iterable();
//如果類型是數(shù)組類型
} else if (rawParameterType.isArray()) {
//獲取數(shù)組類型的類型
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
//同理不能使用MultipartBody.Part.和有值的@Part 注解
if (MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
throw parameterError(p, "@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
}
//獲取輸出是RequestBody的轉(zhuǎn)化器
Converter<?, RequestBody> converter =
retrofit.requestBodyConverter(arrayComponentType, annotations, methodAnnotations);
// 返回ParameterHandler內(nèi)部類Part的實(shí)例龙优,然后調(diào)用的array()方法返回一個(gè)ParameterHandler對(duì)象
return new ParameterHandler.Part<>(headers, converter).array();
//如果既不是數(shù)組也是Iterable,但是普通類型也不能讓@Part的值有值且同時(shí)使用MultipartBody.Part
} else if (MultipartBody.Part.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
} else {
//不是MultipartBody.Par類型羊异,則獲取輸出是RequestBody的轉(zhuǎn)化器
Converter<?, RequestBody> converter =
retrofit.requestBodyConverter(type, annotations, methodAnnotations);
//構(gòu)建ParameterHandler的靜態(tài)內(nèi)部類Part
return new ParameterHandler.Part<>(headers, converter);
}
}
//如果是@PartMap 注解
} else if (annotation instanceof PartMap) {
//沒有使用@isMultipart 拋異常。
if (!isMultipart) {
throw parameterError(p, "@PartMap parameters can only be used with multipart encoding.");
}
//給gotPart賦值
gotPart = true;
//獲取原始類型
Class<?> rawParameterType = Utils.getRawType(type);
//如果不是Map的類型彤断,則拋異常
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@PartMap parameter type must be Map.");
}
//獲取類型的超類
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
//參數(shù)類型判斷
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p, "Map must include generic types (e.g., Map<String, String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) mapType;
//獲取key的類型
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
//排除key不是String的類型
if (String.class != keyType) {
throw parameterError(p, "@PartMap keys must be of type String: " + keyType);
}
//獲取value的類型
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
//@PartMap 不能和 @MultipartBody.Part 一起使用
if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(valueType))) {
throw parameterError(p, "@PartMap values cannot be MultipartBody.Part. "
+ "Use @Part List<Part> or a different value type instead.");
}
//獲取輸出是RequestBody的 轉(zhuǎn)換器
Converter<?, RequestBody> valueConverter =
retrofit.requestBodyConverter(valueType, annotations, methodAnnotations);
PartMap partMap = (PartMap) annotation;
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類PartMap野舶。
return new ParameterHandler.PartMap<>(valueConverter, partMap.encoding());
// 如果注解是 @Body
} else if (annotation instanceof Body) {
//@Body 注解是不能和 @FormEncoded @Multipart 注解一起使用,如果一起使用拋異常
if (isFormEncoded || isMultipart) {
throw parameterError(p,
"@Body parameters cannot be used with form or multi-part encoding.");
}
//@Body 只能使用一次
if (gotBody) {
throw parameterError(p, "Multiple @Body method annotations found.");
}
// 輸出是RequestBody的 轉(zhuǎn)化器
Converter<?, RequestBody> converter;
try {
converter = retrofit.requestBodyConverter(type, annotations, methodAnnotations);
} catch (RuntimeException e) {
// Wide exception range because factories are user code.
throw parameterError(e, p, "Unable to create @Body converter for %s", type);
}
//給gotBody賦值為true
gotBody = true;
//構(gòu)建ParameterHandler的內(nèi)部靜態(tài)類Body宰衙。
return new ParameterHandler.Body<>(converter);
}
//如果上面都處理平道,則說明使用了一個(gè)非Retrofit的的注解,返回null
return null; // Not a Retrofit annotation.
}
內(nèi)容如下:
主要是根據(jù)具體的參數(shù)注解類型供炼,然后具體處理一屋。
補(bǔ)充一個(gè)問題:
Path注解與Url注解不能同時(shí)使用窘疮,否則會(huì)拋出paramterError錯(cuò)誤,其實(shí)原因有很好理解冀墨,Path注解用于替換url路徑中參數(shù)闸衫,這就要求在使用path注解時(shí),必須贏存在請(qǐng)求路徑诽嘉,不然沒法替換路徑中指定的參數(shù)楚堤,而Url注解是在參數(shù)中指定的請(qǐng)求路徑的,這個(gè)時(shí)候指定請(qǐng)求路徑已經(jīng)晚了含懊,path注解找不到請(qǐng)求路徑身冬,更別提更換請(qǐng)求路徑中的參數(shù)了。
3.2.10岔乔、 Builder的方法validatePathName解析
看方法名字 是檢驗(yàn)路徑名字
private void validatePathName(int p, String name) {
if (!PARAM_NAME_REGEX.matcher(name).matches()) {
throw parameterError(p, "@Path parameter name must match %s. Found: %s",
PARAM_URL_REGEX.pattern(), name);
}
// Verify URL replacement name is actually present in the URL path.
if (!relativeUrlParamNames.contains(name)) {
throw parameterError(p, "URL \"%s\" does not contain \"{%s}\".", relativeUrl, name);
}
}
根據(jù)正則表達(dá)式酥筝,來判斷url是否正確
3.2.11、 Builder的方法createResponseConverter解析
通過方法名雏门,我們猜是創(chuàng)建響應(yīng)轉(zhuǎn)化器
private Converter<ResponseBody, T> createResponseConverter() {
//獲取方法的注解
Annotation[] annotations = method.getAnnotations();
try {
//調(diào)用retrofit的responseBodyConverter()方法來獲取一個(gè)輸入是ResponseBody的轉(zhuǎn)化器
return retrofit.responseBodyConverter(responseType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create converter for %s", responseType);
}
}
主要是調(diào)用Retrofit的responseBodyConverter()來獲取輸入是ResponseBody的轉(zhuǎn)化器嘿歌,關(guān)于Retrofit我下面再介紹
3.2.12、 Builder的方法methodError解析
主要就是輸出錯(cuò)誤信息
private RuntimeException methodError(String message, Object... args) {
return methodError(null, message, args);
}
private RuntimeException methodError(Throwable cause, String message, Object... args) {
message = String.format(message, args);
return new IllegalArgumentException(message
+ "\n for method "
+ method.getDeclaringClass().getSimpleName()
+ "."
+ method.getName(), cause);
}
3.2.13茁影、 Builder的方法parameterError解析
輸出參數(shù)錯(cuò)誤
private RuntimeException parameterError(
Throwable cause, int p, String message, Object... args) {
return methodError(cause, message + " (parameter #" + (p + 1) + ")", args);
}
private RuntimeException parameterError(int p, String message, Object... args) {
return methodError(message + " (parameter #" + (p + 1) + ")", args);
}
至此宙帝,ServiceMethod類已經(jīng)講解完畢了,大家對(duì)這個(gè)類熟悉了嗎募闲?
ok步脓,我們來看最后一個(gè)類Retrofit類
三、Retrofit
(一) 類注釋
老規(guī)矩先來認(rèn)識(shí)下這個(gè)類浩螺,首先看這個(gè)類的注釋
Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to define how requests are made. Create instances using {@linkplain Builder the builder} and pass your interface to {@link #create} to generate an implementation.
翻譯一下:
Retroft把一個(gè)java接口的抽象方法 適配/轉(zhuǎn)化 成一個(gè)HTTP的請(qǐng)求靴患,它內(nèi)部是使用解析接口內(nèi)部的抽象方法上的注解來定義如何去發(fā)起請(qǐng)求。通過Builder可以創(chuàng)建Retroft的實(shí)例要出,通過調(diào)用create()方法來創(chuàng)建一個(gè)接口的具體實(shí)現(xiàn)類鸳君。
(二) 類代碼解析
由于這個(gè)類的代碼比價(jià)長(zhǎng),我就不全部粘貼患蹂,等用到時(shí)候再一一粘貼
1或颊、變量解析
那我們來看下他對(duì)應(yīng)的變量,內(nèi)容不多也比較簡(jiǎn)單,比較復(fù)雜的传于,我直接在上注釋了囱挑。
//serviceMethod對(duì)象集合的緩存,用于重用格了,由于里面用到了反射看铆,大家知道反射比較消耗性能,所以為了避免重復(fù)反射盛末,節(jié)約性能弹惦,使用緩存否淤,保證只反射一次。
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
//轉(zhuǎn)化工廠 集合
final List<Converter.Factory> converterFactories;
// 請(qǐng)求適配工廠 集合
final List<CallAdapter.Factory> adapterFactories;
// 回調(diào)的線程池
final Executor callbackExecutor;
//如果為true棠隐,程序是在做一個(gè)預(yù)處理的操作石抡,只是提前創(chuàng)建了一些MethodHandler對(duì)象在緩存中。
final boolean validateEagerly;
- 以上所有變量都是final的助泽,所以構(gòu)造的時(shí)候賦值了啰扛,不會(huì)二次賦值
- 這里提一下validateEagerly變量,他是和eagerlyValidateMethods對(duì)應(yīng)的嗡贺,后面再詳細(xì)講解隐解。
2、構(gòu)造函數(shù)解析
Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
List<Converter.Factory> converterFactories, List<CallAdapter.Factory> adapterFactories,
Executor callbackExecutor, boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = unmodifiableList(converterFactories); // Defensive copy at call site.
this.adapterFactories = unmodifiableList(adapterFactories); // Defensive copy at call site.
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
- 構(gòu)造函數(shù)很簡(jiǎn)單诫睬,就是賦值
- 里面調(diào)用了Collections.unmodifiableList的方法檢查是否是List煞茫,注意他的導(dǎo)包"import static java.util.Collections.unmodifiableList",值得我們學(xué)習(xí)。
- 構(gòu)造既不是public也不是private摄凡,所以不能在包外直接new续徽,所以我們要通過Builder來創(chuàng)建Retrofit對(duì)象
3、相關(guān)方法解析
由于create比較關(guān)鍵亲澡,我們最后解析
3.1钦扭、eagerlyValidateMethods方法解析
private void eagerlyValidateMethods(Class<?> service) {
//獲取平臺(tái)對(duì)象,安卓對(duì)象是Platform.Android
Platform platform = Platform.get();
//獲取service類的所有方法床绪,然后遍歷它的所有方法
for (Method method : service.getDeclaredMethods()) {
//由于Platform.Android沒有實(shí)現(xiàn)isDefaultMethod方法客情,所以默認(rèn)返回false
if (!platform.isDefaultMethod(method)) {
//調(diào)用loadServiceMethod()方法導(dǎo)入方法
loadServiceMethod(method);
}
}
}
具體流程如下:
- 1、收取平臺(tái)對(duì)象
- 2会涎、獲取所有類的所有方法裹匙,這里補(bǔ)充一個(gè)知識(shí)點(diǎn):getDeclaredMethods()方法返回的是類或接口聲明的所有方法,包括public末秃、protect、private籽御、默認(rèn)的方法练慕,但不包括它繼承的方法。當(dāng)然也包括它所有實(shí)現(xiàn)接口的方法技掏。getMethods()返回的是某個(gè)類的所有public的方法铃将,包括其繼承類的public方法,也包括實(shí)現(xiàn)接口的方法哑梳。
- 3劲阎、遍歷這類的所有方法
- 4、由于Platform.Android沒有重寫isDefaultMethod()鸠真,所以platform.isDefaultMethod(method)默認(rèn)返回false悯仙,Platform.Java8是重寫了這個(gè)方法的龄毡,大家有興趣的話可以去研究下。
- 5锡垄、調(diào)用loadServiceMethod()方法
那么就讓我們研究下loadServiceMethod這個(gè)方法
3.2沦零、loadServiceMethod方法解析
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//從緩沖中取出
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
//如果緩存中有,直接取出
if (result != null) return result;
//如果緩存中沒有货岭,加上同步鎖
synchronized (serviceMethodCache) {
//加上鎖后路操,為了保證實(shí)時(shí)性,再去一次
result = serviceMethodCache.get(method);
//如果還沒有
if (result == null) {
//直接構(gòu)建一個(gè)ServiceMethod.Builder對(duì)象千贯,然后調(diào)用ServiceMethod.Builder的builer方法構(gòu)建一個(gè)ServiceMethod對(duì)象關(guān)于build方法剛剛講過哦
result = new ServiceMethod.Builder<>(this, method).build();
把這個(gè)ServiceMethod 對(duì)象放入緩存中
serviceMethodCache.put(method, result);
}
}
//返回這個(gè)ServiceMethod 對(duì)象
return result;
}
其實(shí)看上面方法屯仗,其實(shí)就是一個(gè)一級(jí)緩存。先判斷緩存中有沒有搔谴,如果緩存中有魁袜,則直接返回,如果緩存沒有己沛,則獲取一個(gè)慌核,并添加到緩存中。
3.3申尼、callFactory()垮卓、baseUrl()、callAdapterFactories() 师幕、converterFactories()方法解析由于這四個(gè)方法比較簡(jiǎn)單粟按,其實(shí)就是get方法獲對(duì)應(yīng)的屬性,沒什么好說的霹粥,就簡(jiǎn)單貼下代碼灭将,大家看下就好。
/**
* The factory used to create {@linkplain okhttp3.Call OkHttp calls} for sending a HTTP requests.
* Typically an instance of {@link OkHttpClient}.
*/
public okhttp3.Call.Factory callFactory() {
return callFactory;
}
/** The API base URL. */
public HttpUrl baseUrl() {
return baseUrl;
}
/**
* Returns a list of the factories tried when creating a
* {@linkplain #callAdapter(Type, Annotation[])} call adapter}.
*/
public List<CallAdapter.Factory> callAdapterFactories() {
return adapterFactories;
}
/**
* Returns a list of the factories tried when creating a
* {@linkplain #requestBodyConverter(Type, Annotation[], Annotation[]) request body converter}, a
* {@linkplain #responseBodyConverter(Type, Annotation[]) response body converter}, or a
* {@linkplain #stringConverter(Type, Annotation[]) string converter}.
*/
public List<Converter.Factory> converterFactories() {
return converterFactories;
}
3.4后控、callAdapter() 方法解析
在上面ServiceMethod類中可是調(diào)用過這個(gè)方法的庙曙,大家還記得在哪里調(diào)用嗎?是在ServiceMethod類中createCallAdapter()方法里面最后return的時(shí)候調(diào)用了,那我們來看下源碼
/**
* Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
* #callAdapterFactories() factories}.
*
* @throws IllegalArgumentException if no call adapter available for {@code type}.
*/
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
通過方法注釋我們知道
從callAdapterFactories里面找到合適的CallAdapter浩淘,這個(gè)CallAdapter的返回值類型是returnType
大家看代碼捌朴,其實(shí)內(nèi)部調(diào)用的是nextCallAdapter()方法,那我們就來看下nextCallAdapter()方法
3.5张抄、nextCallAdapter()方法解析
/**
* Returns the {@link CallAdapter} for {@code returnType} from the available {@linkplain
* #callAdapterFactories() factories} except {@code skipPast}.
*
* @throws IllegalArgumentException if no call adapter available for {@code type}.
*/
public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
//非空判斷
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
//獲取skipPast的位置砂蔽,skpiPost屬于被拋棄的一方
int start = adapterFactories.indexOf(skipPast) + 1;
//如果skipPast是null,則start=-1,如果skipPast存在則從skipPast的下一個(gè)位置開始遍歷
for (int i = start, count = adapterFactories.size(); i < count; i++) {
//通過CallAdapter.Factory的get方法來獲取對(duì)應(yīng)的CallAdapter
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
//如果adapter不為null署惯,則返回adapter
return adapter;
}
}
// 如果遍歷了左驾,還是沒有合適的,則拋異常,下面只不過在拼接錯(cuò)誤信息
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(adapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = adapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
先來看下方法的注釋:
除了skipPast(這個(gè)對(duì)象外)诡右,從callAdapterFactories里面再找一個(gè)返回類型是returnType的CallAdapter 對(duì)象
內(nèi)容很簡(jiǎn)單安岂,主要是遍歷callAdapterFactories里面,找到合適的CallAdapter稻爬,如果沒有則拋出異常嗜闻。
3.6、requestBodyConverter()方法解析
/**
* Returns a {@link Converter} for {@code type} to {@link RequestBody} from the available
* {@linkplain #converterFactories() factories}.
*
* @throws IllegalArgumentException if no converter available for {@code type}.
*/
public <T> Converter<T, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
return nextRequestBodyConverter(null, type, parameterAnnotations, methodAnnotations);
}
從converterFactories里面找到一個(gè)合適的Converter桅锄,這個(gè)Converter的輸出類型是RequestBody琉雳。
其實(shí)內(nèi)部調(diào)用的是nextRequestBodyConverter,那我們看下這個(gè)nextRequestBodyConverter接口
3.7友瘤、nextRequestBodyConverter()方法解析
/**
* Returns a {@link Converter} for {@code type} to {@link RequestBody} from the available
* {@linkplain #converterFactories() factories} except {@code skipPast}.
*
* @throws IllegalArgumentException if no converter available for {@code type}.
*/
public <T> Converter<T, RequestBody> nextRequestBodyConverter(Converter.Factory skipPast,
Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations) {
//非空檢查
checkNotNull(type, "type == null");
checkNotNull(parameterAnnotations, "parameterAnnotations == null");
checkNotNull(methodAnnotations, "methodAnnotations == null");
//獲取被放棄的skipPast對(duì)象的位置翠肘,然后加1
int start = converterFactories.indexOf(skipPast) + 1;
//遍歷converterFactories
for (int i = start, count = converterFactories.size(); i < count; i++) {
//獲取對(duì)應(yīng)的 Converter.Factory對(duì)象,然后調(diào)用requestBodyConverter()方法辫秧,
Converter.Factory factory = converterFactories.get(i);
Converter<?, RequestBody> converter =
factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);
//由于requestBodyConverter()默認(rèn)是返回null束倍,所以只有重寫過才會(huì)不為null
if (converter != null) {
//noinspection unchecked
return (Converter<T, RequestBody>) converter;
}
}
// 如果遍歷了,還是沒有合適的盟戏,則拋異常绪妹,下面只不過在拼接錯(cuò)誤信息
StringBuilder builder = new StringBuilder("Could not locate RequestBody converter for ")
.append(type)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = converterFactories.size(); i < count; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
先來說下方法的注釋
除了skipPast(這個(gè)對(duì)象外),從converterFactories里面再找輸出類型是RequestBody的converter 對(duì)象
內(nèi)容很簡(jiǎn)單
有點(diǎn)類似于nextCallAdapter()柿究,主要是遍歷converterFactories邮旷,找到合適的converter,如果沒有則拋出異常蝇摸。
3.8婶肩、responseBodyConverter()方法解析
/**
* Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
* {@linkplain #converterFactories() factories}.
*
* @throws IllegalArgumentException if no converter available for {@code type}.
*/
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
先看下方法的注釋
從converterFactories里面找到一個(gè)合適的Converter,這個(gè)Converter的輸如類型是ResponseBody貌夕。
其實(shí)內(nèi)部調(diào)用時(shí)的nextResponseBodyConverter()律歼,那我們來看下nextResponseBodyConverter()的具體實(shí)現(xiàn)。
3.9啡专、nextResponseBodyConverter()方法解析
/**
* Returns a {@link Converter} for {@link ResponseBody} to {@code type} from the available
* {@linkplain #converterFactories() factories} except {@code skipPast}.
*
* @throws IllegalArgumentException if no converter available for {@code type}.
*/
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
Type type, Annotation[] annotations) {
//非空判斷
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
//獲取被放棄的skipPast的位置险毁,如果是null則是-1
int start = converterFactories.indexOf(skipPast) + 1;
//遍歷converterFactories
for (int i = start, count = converterFactories.size(); i < count; i++) {
//通過responseBodyConverter()來獲取一個(gè)輸入是ResponseBody的Converter
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
//如果Converter不為null,則說明找到了
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
// 如果遍歷了们童,還是沒有合適的辱揭,則拋異常,下面只不過在拼接錯(cuò)誤信息
StringBuilder builder = new StringBuilder("Could not locate ResponseBody converter for ")
.append(type)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = converterFactories.size(); i < count; i++) {
builder.append("\n * ").append(converterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
先看下注釋
除了skipPast(這個(gè)對(duì)象外)病附,從converterFactories里面再找一個(gè)輸入類型是ResponseBody的Converter 對(duì)象
通過閱讀源碼,我們發(fā)現(xiàn):
有點(diǎn)類似于nextRequestBodyConverter()亥鬓,主要是遍歷converterFactories完沪,找到合適的converter,如果沒有則拋出異常。
3.10覆积、stringConverter()方法解析
/**
* Returns a {@link Converter} for {@code type} to {@link String} from the available
* {@linkplain #converterFactories() factories}.
*/
public <T> Converter<T, String> stringConverter(Type type, Annotation[] annotations) {
//非空判斷
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
//獲取對(duì)應(yīng)的 Converter.Factory對(duì)象
for (int i = 0, count = converterFactories.size(); i < count; i++) {
//然后調(diào)用stringConverter()方法獲取對(duì)應(yīng)的Converter對(duì)象
Converter<?, String> converter =
converterFactories.get(i).stringConverter(type, annotations, this);
//非空判斷听皿,因?yàn)槿绻也坏剑瑒t返回null
if (converter != null) {
//noinspection unchecked
return (Converter<T, String>) converter;
}
}
// 如果遍歷了宽档,還是沒有合適的尉姨,調(diào)用默認(rèn)的轉(zhuǎn)換器的toString()方法,默認(rèn)的轉(zhuǎn)換器是BuiltInConverters
// Nothing matched. Resort to default converter which just calls toString().
//noinspection unchecked
return (Converter<T, String>) BuiltInConverters.ToStringConverter.INSTANCE;
}
先來看下方法的注釋吗冤,翻譯一下:
從converterFactories里面找到一個(gè)合適的Converter又厉,這個(gè)Converter的輸出類型是RequestBody。
實(shí)際內(nèi)容也很簡(jiǎn)單椎瘟,遍歷converterFactories覆致。獲取Converter.Factory對(duì)象,調(diào)用這個(gè)對(duì)象的stringConverter()來獲取Converter對(duì)象肺蔚,如果Converter不為空煌妈,則證明取到了,如果沒有取到宣羊,則調(diào)用默認(rèn)的轉(zhuǎn)化器來轉(zhuǎn)化璧诵。
3.11、callbackExecutor()方法解析
/**
* The executor used for {@link Callback} methods on a {@link Call}. This may be {@code null},
* in which case callbacks should be made synchronously on the background thread.
*/
public Executor callbackExecutor() {
return callbackExecutor;
}
先翻譯一下
這個(gè)線程池被用來執(zhí)行一個(gè)請(qǐng)求的回調(diào)仇冯,在這種情況下之宿,回調(diào)應(yīng)該在后臺(tái)線程上同步進(jìn)行。
其實(shí)就會(huì)返回回調(diào)的線程池
3.12赞枕、newBuilder()方法解析
代碼很簡(jiǎn)單澈缺,就是new一個(gè)Builder對(duì)象并返回
public Builder newBuilder() {
return new Builder(this);
}
(三) 靜態(tài)內(nèi)部類Builder解析
1、老規(guī)矩先來看下類的注釋
/**
* Build a new {@link Retrofit}.
* <p>
* Calling {@link #baseUrl} is required before calling {@link #build()}. All other methods
* are optional.
*/
翻譯一下:
通過調(diào)用一個(gè)build()方法來構(gòu)建一個(gè)Retrofit對(duì)象炕婶,在build()之前需要調(diào)用baseUrl()方法姐赡,所有其他方法都是可選的。
2柠掂、看下變量
變量不多项滑,我直接上注釋了
//平臺(tái)
private final Platform platform;
//okhttp3的callFactory
private okhttp3.Call.Factory callFactory;
//HttpUrl
private HttpUrl baseUrl;
//converterFactories集合
private final List<Converter.Factory> converterFactories = new ArrayList<>();
//adapterFactories 集合
private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
//回調(diào)線程池
private Executor callbackExecutor;
//是否需要提前檢查的布爾變量
private boolean validateEagerly;
通過上述代碼我們可以得出以下信息
- 1、converterFactories和adapterFactories一定是不為null的
- 2涯贞、platform是final的枪狂,初始化的時(shí)候一定要賦值的
3、構(gòu)造函數(shù)
Builder有三個(gè)構(gòu)造函數(shù)宋渔,一個(gè)是無參的public州疾,兩個(gè)是包內(nèi)的,所以皇拣,外部調(diào)用一定是new無參的構(gòu)造函數(shù)
Builder(Platform platform) {
this.platform = platform;
// 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());
}
public Builder() {
this(Platform.get());
}
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
converterFactories.addAll(retrofit.converterFactories);
adapterFactories.addAll(retrofit.adapterFactories);
// Remove the default, platform-aware call adapter added by build().
adapterFactories.remove(adapterFactories.size() - 1);
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
- 1严蓖、無參數(shù)的構(gòu)造函數(shù)其實(shí)內(nèi)部調(diào)用的是入?yún)⑹荘latform的構(gòu)造函數(shù)薄嫡,Platform.get()方法我們前面已經(jīng)說過了,返回的是Android對(duì)象
- 2颗胡、入?yún)⑹莗latform的構(gòu)造函數(shù)毫深,內(nèi)部add了一個(gè)BuiltInConverters對(duì)象,可見converterFactories至少是一個(gè)轉(zhuǎn)化器的毒姨。
- 3哑蔫、入?yún)⒌氖荝etrofit的構(gòu)造函數(shù),其實(shí)就是把Retrofit的屬性賦值給Builder
4弧呐、相關(guān)方法解析
4.1闸迷、client方法和callFactory
/**
* The HTTP client used for requests.
* <p>
* This is a convenience method for calling {@link #callFactory}.
* 通過callFactory作為客戶端,來發(fā)起HTTP請(qǐng)求是非常便捷的泉懦。
*/
public Builder client(OkHttpClient client) {
return callFactory(checkNotNull(client, "client == null"));
}
/**
* Specify a custom call factory for creating {@link Call} instances.
* <p>
* Note: Calling {@link #client} automatically sets this value.
* 通過自定義的call factory 來創(chuàng)建一個(gè)請(qǐng)求(Call)的實(shí)例稿黍,調(diào)用client會(huì)自動(dòng)設(shè)置
*/
public Builder callFactory(okhttp3.Call.Factory factory) {
this.callFactory = checkNotNull(factory, "factory == null");
return this;
}
通過上面我們可知
- client內(nèi)部調(diào)用的callFactory方法
- 這兩個(gè)方法表明,Retrofit底層是使用okHttp崩哩,而且是強(qiáng)關(guān)聯(lián)巡球。
- PS:第一次看代碼的哥們可能會(huì)有疑惑,這里補(bǔ)充下OkHttpClient是okhttp3.Call.Factory的實(shí)現(xiàn)類邓嘹。
4.2酣栈、baseUrl方法
Builder有兩個(gè)baseUrl,只不過是入?yún)⒉煌研谘海屛覀儊砜聪略创a
/**
* Set the API base URL.
*
* @see #baseUrl(HttpUrl)
*/
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
//收到篇幅限制矿筝,注釋太長(zhǎng)我直接省略
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
- 主要是設(shè)置基本的url,一般是請(qǐng)求的url的前綴
- 受篇幅限制棚贾,我這邊沒有粘貼注釋窖维,不過注釋非常不錯(cuò),我建議大家還是去看看妙痹,里面主要講解拼接的注意事件铸史。
4.3、addConverterFactory()和addCallAdapterFactory方法
/** Add converter factory for serialization and deserialization of objects. */
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
/**
* Add a call adapter factory for supporting service method return types other than {@link
* Call}.
*/
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
adapterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
addConverterFactory()和addCallAdapterFactory方法比較簡(jiǎn)單怯伊,就是向?qū)?yīng)的集合添加元素而已
4.4琳轿、callbackExecutor()和validateEagerly方法
/**
* The executor on which {@link Callback} methods are invoked when returning {@link Call} from
* your service method.
* <p>
* Note: {@code executor} is not used for {@linkplain #addCallAdapterFactory custom method
* return types}.
*/
public Builder callbackExecutor(Executor executor) {
this.callbackExecutor = checkNotNull(executor, "executor == null");
return this;
}
/**
* When calling {@link #create} on the resulting {@link Retrofit} instance, eagerly validate
* the configuration of all methods in the supplied interface.
*/
public Builder validateEagerly(boolean validateEagerly) {
this.validateEagerly = validateEagerly;
return this;
}
這兩個(gè)方法也比較簡(jiǎn)單,就是給兩個(gè)變量賦值
4.5耿芹、build()方法
/**
* Create the {@link Retrofit} instance using the configured values.
* <p>
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
public Retrofit build() {
//如果沒有配置過baseUrl崭篡,則拋異常
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//獲取callFactory
okhttp3.Call.Factory callFactory = this.callFactory;
//如果為null,則沒有調(diào)用過client()和callFactory()方法
if (callFactory == null) {
//創(chuàng)建一個(gè)OkHttpClient對(duì)象,作為默認(rèn)的callFactory
callFactory = new OkHttpClient();
}
//獲取回調(diào)的線程池
Executor callbackExecutor = this.callbackExecutor;
// 如果callbackExecutor為null,則沒有設(shè)置過回調(diào)線程池吧秕,
if (callbackExecutor == null) {
//獲取平臺(tái)默認(rèn)的線程池琉闪,其實(shí)就是主線程
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
// 給adapterFactories賦值
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
//添加一個(gè)默認(rèn)的callAdapter,其實(shí)是DefaultCallAdapterFactory
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
// 設(shè)置converterFactories砸彬,它默認(rèn)是含有BuiltInConverters對(duì)象的
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
//構(gòu)建一個(gè)Retrofit對(duì)象
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
先看下注釋
通知使用配置過的值來創(chuàng)建Retrofit對(duì)象塘偎,如果沒有調(diào)用client()和callFactory()方法疗涉,那么將創(chuàng)建并使用默認(rèn)的OkHttpClient。
代碼很簡(jiǎn)單吟秩,就是初始化屬性,這里重點(diǎn)說下绽淘,如果沒有設(shè)置回調(diào)線程池涵防,則默認(rèn)是主線程,如果沒有配置轉(zhuǎn)化器沪铭,則默認(rèn)使用BuiltInConverters壮池,如果沒配置callAdapter,則默認(rèn)使用DefaultCallAdapterFactory杀怠。
(四) create()方法解析
這個(gè)方法很重要椰憋,由于受到篇幅限制,我就不粘貼注釋的了赔退,我們先來看下源碼
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
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();
@Override public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
//如果定義方法的類的類型是Object橙依,或者說,是Object類的方法硕旗,則直接執(zhí)行invoke調(diào)用
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
// Android平臺(tái)沒有重寫這個(gè)方法窗骑,所以默認(rèn)是false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//調(diào)用loadServiceMethod獲取一個(gè)ServiceMethod對(duì)象,其內(nèi)部是一個(gè)一級(jí)緩存漆枚,內(nèi)存中有直接取內(nèi)存中的创译,內(nèi)存中沒有構(gòu)建一個(gè)ServiceMethod,放入到緩存中墙基。
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//使用serviceMethod和args來構(gòu)建一個(gè)OkHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//調(diào)用serviceMethod對(duì)象的callAdapter對(duì)象的adapt方法软族。
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
通過源碼我們知道,這方法內(nèi)部的流程如下:
- 檢查 接口類残制,判斷是否是接口立砸,判斷是否繼承其他接口
- 做是否需要預(yù)加載
- 調(diào)用動(dòng)態(tài)代理獲取一個(gè)類的對(duì)象
然后我們看下InvocationHandler里面的invoke()方法里面的實(shí)現(xiàn)流程
- 先判斷這個(gè)方法是不是Object的方法,如果是直接接調(diào)用invoke
- 根據(jù)平臺(tái)的特性痘拆,決定是否調(diào)用invokeDefaultMethod()方法
- 通過調(diào)用loadServiceMethod()方法載入一個(gè)ServiceMethod對(duì)象仰禽。
- 用ServiceMethod來構(gòu)建一個(gè)OkHttpCall。
- 最后調(diào)用serviceMethod對(duì)象的callAdapter對(duì)象的adapt方法
最后翻譯了一下這個(gè)方法對(duì)應(yīng)的注釋纺蛆,受篇幅限制吐葵,我就不粘貼源碼了,直接上我們翻譯后的內(nèi)容了
創(chuàng)建一個(gè)由服務(wù)器定義的API接口的具體實(shí)現(xiàn)桥氏。如果在抽象接口的方法上通過添加注解來實(shí)現(xiàn)設(shè)置定義請(qǐng)求方式温峭,而相對(duì)路徑的url是根據(jù)這個(gè)請(qǐng)求方式來的。請(qǐng)求方式有@link retrofit2.http.GET 代表GET請(qǐng)求字支,@link retrofit2.http.PUT 代表PUT請(qǐng)求凤藏,@retrofit2.http.POST奸忽,代表POST請(qǐng)求,@retrofit2.http.PATCH 代表PATCH請(qǐng)求揖庄,@retrofit2.http.HEAD 代表HEAD請(qǐng)求栗菜,
@retrofit2.http.DELETE 代表DELETE請(qǐng)求, @retrofit2.http.OPTIONS 代表OPTIONS請(qǐng)求蹄梢,通過使用@HTTP疙筹,你也可以自定義HTTP請(qǐng)求方式。如果你想動(dòng)態(tài)設(shè)置url禁炒,第一個(gè)入?yún)⑿枰褂聾Url 注解來實(shí)現(xiàn)檀夹』冢可以在方法參數(shù)里面使用@Path注解,是實(shí)現(xiàn)替換Url部分內(nèi)容,被替換的部分需要用大括號(hào)“{}”括起來督赤,例如"{foo}"陕凹。如果想在URL上添加查詢字段树碱,就要使用@Query 注解记罚。用@ Body 來表示一個(gè)請(qǐng)求體。一個(gè)對(duì)象的實(shí)例將會(huì)被Converter.Factory的實(shí)例轉(zhuǎn)化為網(wǎng)絡(luò)請(qǐng)求玛痊。一個(gè)RequestBody也可以作為原始數(shù)據(jù)而直接使用汰瘫。方法注解和參數(shù)注解支持如下的格式:通過@FormUrlEncoded,代表表單提交擂煞,由@Field注解 代表表單數(shù)據(jù)混弥。@multipart 代表多部分,在入?yún)⑸鲜褂米⒔釦Part表示每一部分的具體數(shù)據(jù)对省。通過在方法上添加@Header 和@Header來添加請(qǐng)求頭的數(shù)據(jù)蝗拿。默認(rèn)情況下,這個(gè)方法返回一個(gè)代表HTTP請(qǐng)求的Call對(duì)象蒿涎,里面的泛型是響應(yīng)體的類型哀托,由 Converter.Factory對(duì)象負(fù)責(zé)轉(zhuǎn)化,也可以用ResponseBody代表原始數(shù)據(jù)劳秋,當(dāng)然你不關(guān)心請(qǐng)求體仓手,也可以設(shè)置Void。