基于retrofit2.1.0
核心类介绍
ParameterHandler 解析方法参数的注解获取他们信息,然后调用转换器,然后设置到RequestBuilder
不同的注解有不同的ParameterHandler 实现
Converter
Converter.Factory
核心方法:responseBodyConverter 根据adapter中的ResponseType,类型来解析数据
requestBodyConverter Body ,PartMap,Part方法参数中的这三个注解,都是需要把数据,转化为RequestBody类型的
stringConverter //把各种类型的数据转化为String,主要用在,对于方法的请求参数,的注解的数据类型进行转换,转换为String,然后设置到RequestBuilder
ServiceMethod:指责很多
1.获取方法和参数的注解
2.根据adapter返回值的类型,和根据参数的类型获取就行的Converter.Factory ,创建对应的Converter
3.然后解析方法的注解,解析参数的注解(ParameterHandler),很多都要依赖Converter
4.根据解析的数据,配合ParameterHandler,创建RequestBuilder
5.创建请求Request
6.使用responseBodyConverter解析请求
CallAdapter.Factory:根据定义的接口中返回的类型,返回指定的Factory
可以把Call转化为任意的返回值,让我们以自定义的方式,触发请求,并且可以自定义对相应的统一处理,然后给出自定义的回调。
方法参数注解概述
Query 设置查询参数,key=value
Path 用来替换相对路径中的值
Url 再参数中设置相对路径
QueryMap 设置多个查询参数,设置一个map子类 ,并且key必须要是String,value的值不限制,但是要负责转化为String
Header 添加请求头
HeaderMap 设置多个请求头,设置一个map子类 ,并且key必须要是String,value的值不限制,但是要负责转化为String
Field 添加表单字段 type 也是可以是任意类型,只要可以转换为String 就可以
FieldMap 添加多个表单字段,key必须为String ,value可以是任意类型
Part 请求Multipart下的一个请求体,和请求头,如果设置了value,就不要使用Okhttp的Part,如果没有设置,就必须要是Okhttp的Part
PartMap 上面的请求的Map形式
Body 直接设置给请求体,需要我们自定义ReuqestBody转换器
上面的注解涵盖了Http请求的各个部分,我们可以通过这些注解标识数据,然后设置他们,并且Retrofit做的非常好的是,只是用注解标识数据再http中的位置,但是注解标识的数据类型,不做限制,可以是任意数据类型,然后我们只要设置对应类型的的数据转换器,就可以了,极大的提高了扩展性,再后面方法参数解析为ParameterHandler的步骤会体现。
代码流程分析
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(NetConfiguration.getInstance().getBaseUrl())//设置BaseUrl
.addConverterFactory(GsonConverterFactory.create(gson))//添加转换器工厂
.addCallAdapterFactory(new ExecutorCallAdapterFactory1())//添加CallAdapter工厂
.client(getGenericClient())//设置CallFactory
.callbackExecutor(null)//设置CallBack执行的线程,可以再主线程或者子线程,再测试的时候很有用
.build();
->构建Retrofit
-》retrofit.create(clazz);
public
Utils.validateServiceInterface(service); //检查接口是否合法,不能有继承接口
if (validateEagerly) {//是否提前解析每一个方法,默认是false,可以再构建的时候设置,会占用内存,但是会提高执行请求的效率
eagerlyValidateMethods(service); //会在内部把Method解析成ServiceMethod
}
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.
if (method.getDeclaringClass() == Object.class) { //如果类是Object定义的,就原样执行
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {//根据平台特性判断,如果是默认方法,就调用对应平台的执行方式
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);//根据Method信息构建ServiceMethod ,核心类,一会具体分析
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);//实现Call,内部会使用serviceMethod,来生成request,并且解析相应
return serviceMethod.callAdapter.adapt(okHttpCall);//调用callAdapter,再适配返回值类型,返回执行类型
}
});
}
分析个对象的构建
-》 ServiceMethod serviceMethod = loadServiceMethod(method);
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);//从缓存中获取,缓存可以太高效率
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();//如果没有重新构建
serviceMethodCache.put(method, result);//并且放入缓存
}
}
return result;
}
-》 new ServiceMethod.Builder(this, method).build();
-》 new ServiceMethod.Builder(this, method)
public Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();//获取方法的注解
this.parameterTypes = method.getGenericParameterTypes();//获取方法参数数组
this.parameterAnnotationsArray = method.getParameterAnnotations();//获取方法参数对应位置的注解,二维数组
}
-》 public ServiceMethod build()
public ServiceMethod build() {
callAdapter = createCallAdapter();//根据接口中定义的返回值类型,从Factory中寻找合适的CallAdapter
responseType = callAdapter.responseType();//CallAdapter,返回,按照这个类型来解析http的相应
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();//根据responseType 返回解析ResponBody的responseConverter
for (Annotation annotation : methodAnnotations) {//遍历方法的注解,然后解析方法的注解,参数保存到Builder
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;
parameterHandlers = new ParameterHandler>[parameterCount];//每一个 parameterHandler负责设置对应注解的相关类型到RequestBuiler,保存了所有的参数的设置器
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
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.");
}
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);//把解析的参数设置到ServiceMethod
}
-》 createCallAdapter();
private CallAdapter> createCallAdapter() {
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
return retrofit.callAdapter(returnType, annotations);//根据返回值类型,返回CallAdapter
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
-》 createResponseConverter();
private Converter
Annotation[] annotations = method.getAnnotations();
try {
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);
}
}
-》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);
if (!Void.class.equals(responseType)) {
throw methodError("HEAD method must use Void as response type.");
}
} 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 = (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("@Headers annotation is empty.");
}
headers = parseHeaders(headersToParse);
} else if (annotation instanceof Multipart) {
if (isFormEncoded) {
throw methodError("Only one encoding annotation is allowed.");
}
isMultipart = true;
} else if (annotation instanceof FormUrlEncoded) {
if (isMultipart) {
throw methodError("Only one encoding annotation is allowed.");
}
isFormEncoded = true;
}
}
-》parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody)//设置解析的请求方法,并且设置相对url
private void parseHttpMethodAndPath(String httpMethod, String value, boolean hasBody) {
if (this.httpMethod != null) {
throw methodError("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.
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("URL query string \"%s\" must not have replace block. "
+ "For dynamic query parameters use @Query.", queryParams);
}
}
this.relativeUrl = value;
this.relativeUrlParamNames = parsePathParameters(value);
}
-》 parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
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(
p, parameterType, annotations, annotation);//各注解解析类似,我们只分析一个
private ParameterHandler> parseParameterAnnotation(
int p, Type type, Annotation[] annotations, Annotation annotation) {
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();
} 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());
} else if (annotation instanceof Query) {
Query query = (Query) annotation;//获取注解
String name = query.value();//返回注解的值
boolean encoded = query.encoded();//是否需要url编码
Class> rawParameterType = Utils.getRawType(type);//获取主类型
gotQuery = true;
if (Iterable.class.isAssignableFrom(rawParameterType)) {//判断是否传递的是一个迭代器类型
if (!(type instanceof ParameterizedType)) {//如果传递了迭代器类型,就一定要传递泛型的具体类型,否则报错,因为要设置数据,所以必须要是具体类型
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter, String> converter =
retrofit.stringConverter(iterableType, annotations);//对迭代器中的类型,调用stringConvert转化为String类型
return new ParameterHandler.Query<>(name, converter, encoded).iterable();//内部会迭代执行,把数据设置到RequestBuilder
} else if (rawParameterType.isArray()) {
Class> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).array();
} else {
Converter, String> converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.Query<>(name, converter, encoded);
}
} else if (annotation instanceof QueryMap) {
Class> rawParameterType = Utils.getRawType(type);
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@QueryMap parameter type must be Map.");
}
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p, "Map must include generic types (e.g., Map
}
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType) {
throw parameterError(p, "@QueryMap keys must be of type String: " + keyType);
}
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
Converter, String> valueConverter =
retrofit.stringConverter(valueType, annotations);
return new ParameterHandler.QueryMap<>(valueConverter, ((QueryMap) annotation).encoded());
} else if (annotation instanceof Header) {
Header header = (Header) annotation;
String name = header.value();
Class> rawParameterType = Utils.getRawType(type);
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter, String> converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Header<>(name, converter).iterable();
} else if (rawParameterType.isArray()) {
Class> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Header<>(name, converter).array();
} else {
Converter, String> converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.Header<>(name, converter);
}
} else if (annotation instanceof HeaderMap) {
Class> rawParameterType = Utils.getRawType(type);
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@HeaderMap parameter type must be Map.");
}
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p, "Map must include generic types (e.g., Map
}
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType) {
throw parameterError(p, "@HeaderMap keys must be of type String: " + keyType);
}
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
Converter, String> valueConverter =
retrofit.stringConverter(valueType, annotations);
return new ParameterHandler.HeaderMap<>(valueConverter);
} else if (annotation instanceof Field) {
if (!isFormEncoded) {
throw parameterError(p, "@Field parameters can only be used with form encoding.");
}
Field field = (Field) annotation;
String name = field.value();
boolean encoded = field.encoded();
gotField = true;
Class> rawParameterType = Utils.getRawType(type);
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter, String> converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Field<>(name, converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
Class> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.Field<>(name, converter, encoded).array();
} else {
Converter, String> converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.Field<>(name, converter, encoded);
}
} else if (annotation instanceof FieldMap) {
if (!isFormEncoded) {
throw parameterError(p, "@FieldMap parameters can only be used with form encoding.");
}
Class> rawParameterType = Utils.getRawType(type);
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@FieldMap parameter type must be Map.");
}
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p,
"Map must include generic types (e.g., Map
}
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType) {
throw parameterError(p, "@FieldMap keys must be of type String: " + keyType);
}
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
Converter, String> valueConverter =
retrofit.stringConverter(valueType, annotations);
gotField = true;
return new ParameterHandler.FieldMap<>(valueConverter, ((FieldMap) annotation).encoded());
} else if (annotation instanceof Part) {
if (!isMultipart) {
throw parameterError(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)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
if (!MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(iterableType))) {
throw parameterError(p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
}
return ParameterHandler.RawPart.INSTANCE.iterable();
} else if (rawParameterType.isArray()) {
Class> arrayComponentType = rawParameterType.getComponentType();
if (!MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
throw parameterError(p,
"@Part annotation must supply a name or use MultipartBody.Part parameter type.");
}
return ParameterHandler.RawPart.INSTANCE.array();
} 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.");
}
} else {
Headers headers =
Headers.of("Content-Disposition", "form-data; name=\"" + partName + "\"",
"Content-Transfer-Encoding", part.encoding());
if (Iterable.class.isAssignableFrom(rawParameterType)) {
if (!(type instanceof ParameterizedType)) {
throw parameterError(p, rawParameterType.getSimpleName()
+ " must include generic type (e.g., "
+ rawParameterType.getSimpleName()
+ "
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
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.");
}
Converter, RequestBody> converter =
retrofit.requestBodyConverter(iterableType, annotations, methodAnnotations);
return new ParameterHandler.Part<>(headers, converter).iterable();
} else if (rawParameterType.isArray()) {
Class> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
if (MultipartBody.Part.class.isAssignableFrom(arrayComponentType)) {
throw parameterError(p, "@Part parameters using the MultipartBody.Part must not "
+ "include a part name in the annotation.");
}
Converter, RequestBody> converter =
retrofit.requestBodyConverter(arrayComponentType, annotations, methodAnnotations);
return new ParameterHandler.Part<>(headers, converter).array();
} 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 {
Converter, RequestBody> converter =
retrofit.requestBodyConverter(type, annotations, methodAnnotations);
return new ParameterHandler.Part<>(headers, converter);
}
}
} else if (annotation instanceof PartMap) {
if (!isMultipart) {
throw parameterError(p, "@PartMap parameters can only be used with multipart encoding.");
}
gotPart = true;
Class> rawParameterType = Utils.getRawType(type);
if (!Map.class.isAssignableFrom(rawParameterType)) {
throw parameterError(p, "@PartMap parameter type must be Map.");
}
Type mapType = Utils.getSupertype(type, rawParameterType, Map.class);
if (!(mapType instanceof ParameterizedType)) {
throw parameterError(p, "Map must include generic types (e.g., Map
}
ParameterizedType parameterizedType = (ParameterizedType) mapType;
Type keyType = Utils.getParameterUpperBound(0, parameterizedType);
if (String.class != keyType) {
throw parameterError(p, "@PartMap keys must be of type String: " + keyType);
}
Type valueType = Utils.getParameterUpperBound(1, parameterizedType);
if (MultipartBody.Part.class.isAssignableFrom(Utils.getRawType(valueType))) {
throw parameterError(p, "@PartMap values cannot be MultipartBody.Part. "
+ "Use @Part List
}
Converter, RequestBody> valueConverter =
retrofit.requestBodyConverter(valueType, annotations, methodAnnotations);
PartMap partMap = (PartMap) annotation;
return new ParameterHandler.PartMap<>(valueConverter, partMap.encoding());
} else if (annotation instanceof Body) {
if (isFormEncoded || isMultipart) {
throw parameterError(p,
"@Body parameters cannot be used with form or multi-part encoding.");
}
if (gotBody) {
throw parameterError(p, "Multiple @Body method annotations found.");
}
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;
return new ParameterHandler.Body<>(converter);
}
return null; // Not a Retrofit annotation.
}
现在数据已经准备好了,开始执行,执行是由请求接口中返回的数据来触发的,虽然返回的类型多种多样
但是,最终内部触发请求,就是调用Retrifit 的OkHttpCall(实现了Call接口)的方法
分析异步请求
OkHttpCall.enqueue(final Callback
@Override public void enqueue(final Callback
if (callback == null) throw new NullPointerException("callback == null");
okhttp3.Call call;
Throwable failure;
synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;
call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();//创建Call,创建的是Okhttp的Call
} catch (Throwable t) {
failure = creationFailure = t;//创建失败
}
}
}
if (failure != null) {
callback.onFailure(this, failure);//创建失败直接走失败回调
return;
}
if (canceled) {
call.cancel();//如果调用了取消请求,就取消请求
}
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response
try {
response = parseResponse(rawResponse);//解析响应
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);//解析成功,走成功回调
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);//走失败回调
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
private void callSuccess(Response
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
-》 call = rawCall = createRawCall();//创建Call,创建的是Okhttp的Call
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);//调用serviceMethod.toRequest(方法参数)创建请求
okhttp3.Call call = serviceMethod.callFactory.newCall(request);//根据请求,调用CallFactory(创建Retrifit的时候设置),生成一个Okhttp的Call
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;//返回Call
}
->Request request = serviceMethod.toRequest(args);//调用serviceMethod.toRequest(方法参数)创建请求
Request toRequest(Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);//根据已经解析的一些基本信息,创建RequestBuilder
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler
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]);//遍历执行请求参数设置器,让设置器把数据设置到,RequestBuilder
}
return requestBuilder.build();//生成请求
}
-》 response = parseResponse(rawResponse);//解析响应
Response
ResponseBody rawBody = rawResponse.body();
// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();
int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}
if (code == 204 || code == 205) {
return Response.success(null, rawResponse);
}
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);//调用serviceMethod.toResponse(catchingBody);转换响应
return Response.success(body, rawResponse);//返回成功响应
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
-》serviceMethod.toResponse(catchingBody);转换响应
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);//调用之前根据adapter返回的responseType获取的ResponeConvert
}
-》返回到最初的create方法,动态代理中
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);//会从 serviceMethod中获取根据接口方法返回值类型解析得到的CallAdapter
调用结束。
扩展使用,根据动态代理的思想,我们可以再接口方法上自定义我们自己的注解,然后是动态代理的时候,我们自己再包一层然后设置一些自己的参数。