接着上一篇Retrofi分析(一)继续分析
下面开始分析创建Retrofit对象和service 对象 这一部分是Retrofit框架的核心部分
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())//设置数据解析器
.baseUrl("https://api.github.com/")//设置请求的URL地址
.build();
GitHubService service = retrofit.create(GitHubService.class);
可以看到 Retrofit 本身是通过构建者模式实现 进入Retrofit 里面 首先看到Retrofit 的一些成员变量,先看看这些成员变量是干什么用的。
public final class Retrofit {
private final Map<Method, ServiceMethod<?, ?>> serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
final List<Converter.Factory> converterFactories;
final List<CallAdapter.Factory> callAdapterFactories;
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
......省略后面代码
因为它是通过builder模式构建的所以builder中的代码也需要看
Builder(Retrofit retrofit) {
platform = Platform.get();
callFactory = retrofit.callFactory;
baseUrl = retrofit.baseUrl;
converterFactories.addAll(retrofit.converterFactories);
// Remove the default BuiltInConverters instance added by build().
converterFactories.remove(0);
callAdapterFactories.addAll(retrofit.callAdapterFactories);
// Remove the default, platform-aware call adapter added by build().
callAdapterFactories.remove(callAdapterFactories.size() - 1);
callbackExecutor = retrofit.callbackExecutor;
validateEagerly = retrofit.validateEagerly;
}
serviceMethodCache :是一个ConcurrentHashMap,主要用于缓存服务方法。以前版本使用的是LinkedHashMap,ConcurrentHashMap是线程安全的。ServiceMethod就是通过上一篇中的注解生成的方法类。
callFactory:在build方法中可以看到if (callFactory == null) {callFactory = new OkHttpClient();}
这个callFactory其实就是我们okhttp中的 核心类OkHttpClient对象。
baseUrl:基地址,通过它和我们自定义的service中定义的相对地址可以拼接出来完整的url请求地址
converterFactories:数据转换器工厂的集合。用来把我们响应回来的数据封装成我们需要的序列化对象。比如上面例子中用到的GsonConverterFactory.addConverterFactory(GsonConverterFactory.create())
。就是把返回的json对象转化成指定的java对象。
官方已经给我们提供了很多种解析工厂,我们自己也可以继承Converter.Factory自己实现。
官方提供的:
看一下GsonConverterFactory的源码
public final class GsonConverterFactory extends Converter.Factory {
/**
* Create an instance using a default {@link Gson} instance for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
public static GsonConverterFactory create() {
return create(new Gson());
}
/**
* Create an instance using {@code gson} for conversion. Encoding to JSON and
* decoding from JSON (when no charset is specified by a header) will use UTF-8.
*/
@SuppressWarnings("ConstantConditions") // Guarding public API nullability.
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private final Gson gson;
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
@Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonResponseBodyConverter<>(gson, adapter);
}
@Override
public Converter<?, RequestBody> requestBodyConverter(Type type,
Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
return new GsonRequestBodyConverter<>(gson, adapter);
}
}
构造方法是private 的不能new,有两个创建方法,create()和create(Gson gson)。内部有一个final的Gson类型的变量gson,在构造GsonConverterFactory被初始化
它两个public方法responseBodyConverter和requestBodyConverter,都是通过gson.getAdapter方法获取TypeAdapter(类型适配器)对象,在把这个TypeAdapter(类型适配器)对象作为构造函数的参数传入GsonResponseBodyConverter和GsonRequestBodyConverter中。其内部就是通过gson库来解析json的逻辑了
callAdapterFactories: call的适配器工厂集合。把call对象转换成其他平台的call对象,默认使用的ExecutorCallAdapterFactory。
如果我们在创建的时候配置了比如使用Rxjava和Retrofit配合,就可以吧Retrofit中的Call对象转换成Rxjava中的Observable对象返回。.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
如果跟RxJava结合开发,官方已经给我们定义好了一个类RxJava2CallAdapterFactory,RxJava2CallAdapterFactory这个类继承了CallAdapter.Factory,而CallAdapter.Factory是接口CallAdapter中的一个抽象类。我们自己也可以继承CallAdapter.Factory来实现自己的适配器类。所以主要看一下CallAdapter这个接口
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call);
abstract class Factory {
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
第一个方法:Type responseType(); ,响应返回类型,比如我们的上一篇GitHubService中定义的Call<List<Repo>> listRepos(@Path("user") String user);
这个返回类型就是List<Repo>>
第二个方法:T adapt(Call call);,T就是我们的Retrofit的Call适配成别的平台的返回的实例。比如RxJava中的Observable对象。
第三个工厂类中的 CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit);
返回一个CallAdapter的实例,如果工厂无法处理则返回null
第四个工厂类中的 Type getParameterUpperBound(int index, ParameterizedType type)
返回index参数的上限
第五个工厂类中的 protected static Class<?> getRawType(Type type)
获取原始的类型例如:List<? extends Runnable>
则返回List.class
callbackExecutor: 回调执行器,主要用来处理异步的网络请求中到主线程的回调。
validateEagerly:是否立即解析接口中的方法,默认是false。如果为true,程序是在做一个预处理的操作,只是提前创建了一些MethodHandler对象在缓存中。
platform: 适配的平台,Android,Java8。它有两个静态内部类分别对应着Android,Java8。下面看一下Android类
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
//默认的请求适配工厂
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
如果判断是Android平台会返回上面的这个对象。defaultCallAdapterFactory是默认的请求适配器工厂,MainThreadExecutor 静态内部类,通过new Handler(Looper.getMainLooper())来获取一个主线程的Handler。然后在执行主线程的时候,调用的是主线程的handler的post方法。我们知道Android中操作UI界面需要在主线程中执行,MainThreadExecutor 就是一个主线程中的执行器。
看完Retrofit对象的创建,就到了下面的一个非常重要的方法了retrofit.create方法,通过这个方法来获取GitHubService 的一个实例
GitHubService service = retrofit.create(GitHubService.class);
GitHubService 就是我们前面定义的接口。
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
然后看retrofit.create()的方法
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, @Nullable Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
首先看一下一个判断,如果我们设置validateEagerly为立即执行,validateEagerly在我们创建Retrofit的时候就创建好了。那么就会执行下面的方法eagerlyValidateMethods(service);
private void eagerlyValidateMethods(Class<?> service) {
//获取平台对象,安卓对象是Platform.Android
Platform platform = Platform.get();
//获取service类的所有方法,然后遍历它的所有方法
for (Method method : service.getDeclaredMethods()) {
//由于Platform.Android没有实现isDefaultMethod方法,所以默认返回false,下面的方法肯定执行
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
boolean isDefaultMethod(Method method) {
return false;
}
这个方法通过反射,找到我们GitHubService中的所有的方法,然后遍历执行 loadServiceMethod(method);方法。由于isDefaultMethod方法永远返回false,说以每个方法都能执行到 loadServiceMethod(method);
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//先从缓冲中取出
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
//如果缓存中有,直接取出
if (result != null) return result;
//如果缓存中没有,加上同步锁
synchronized (serviceMethodCache) {
//加上锁后,为了保证实时性,再去取一次
result = serviceMethodCache.get(method);
if (result == null) {
//如果还没有,直接构建一个ServiceMethod.Builder对象,
//然后调用ServiceMethod.Builder的builer方法构建一个ServiceMethod
result = new ServiceMethod.Builder<>(this, method).build();
//把这个ServiceMethod 对象放入缓存中
serviceMethodCache.put(method, result);
}
}
return result;
}
serviceMethodCache,我们上面创建Retrofit的时候就已经创建了是一个ConcurrentHashMap。用来缓存ServiceMethod,由于反射比较消耗性能,所以为了避免这种性能消耗,我们保证同一个接口(api)的同一个方法,只会创建一次。由于我们每次获取的接口(api)实例都是传入的class对象,而class对象是在进程内单例的,所以获取她的同一个方法Method实例也是单利的,所以这个缓存是有效的。
既然是缓存,逻辑就是如果缓存里面有,则直接从缓存里面拿,如果缓存没有,则new一个ServiceMethod.Builder对象,然后调用它的build()方法来获取一个ServiceMethod,并把它放入serviceMethodCache中,然后返回。
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
this.methodAnnotations = method.getAnnotations();
this.parameterTypes = method.getGenericParameterTypes();
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
Builder构造中,传入了Retrofit 对象和循环出来的方法并赋值。通过这个方法,找到它上面的注解和参数的类型和方法的参数上的注解 比如GitHubService 中的@GET,List,@Path
然后看其build()方法
public ServiceMethod build() {
//获取callAdapter
callAdapter = createCallAdapter();
//通过callAdapter的responseType方法获取响应体类型
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);
}
//如果没有HTTP请求的方法,则抛异常
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
//在上面遍历方法注解并解析方法注解的时候,hasBody,isMultipart,isFormEncoded等已经完成赋值
//如果没有请求体
if (!hasBody) {
//如果使用了@Multipart注解,使用了@Multipart 是必须有消息体的
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
//如果使用了 @FormEncoded,使用了@FormEncoded 是必须有消息体的
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];
//遍历入参的数量
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];
//如果对应入参的注解为null,则抛异常
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
//如果对应的入参注解不为null,则调用parseParameter方法获取ParameterHandler,
//cancel在这里方法里面创建ParameterHandler里面的静态内部类
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
//for循环遍历以后,如果relativeUrl还为null,同时没有使用!@url注解,
//这样的话我们就无法获取url地址了,所以要抛异常。
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
//如果没有使用@FormEncoded注解、@Multipart和,同时HTTP请求方式也不需要响应提,但是却使用了@Body 注解,
//这不是自相矛盾,所以抛异常。
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
//如果使用@FormEncoded注解,却没使用@Field注解,不符合规范,则抛异常
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
//如果使用 @Multipart 注解,却没有使用@Part 注解,抛异常
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
//new一个ServiceMethod对象,入参是Builder自己,然后return这个ServiceMethod对象。
return new ServiceMethod<>(this);
}
**第一步通过createCallAdapter()方法创建了CallAdapter对象。**Call的转化适配器
private CallAdapter<T, R> createCallAdapter() {
//获取方法的返回值类型
Type returnType = method.getGenericReturnType();
//如果方法的返回值类型我们无法处理,则抛出异常
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
//如果方法是void的,则没有返回值
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
//获取方法的注解
Annotation[] annotations = method.getAnnotations();
try {
//调用retrofit的callAdapter来获取一个CallAdapter对象
return (CallAdapter<T, R>) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
可以看到,首先拿到方法的返回类型,判断这个返回类型合不合法是不是void之后拿到方法的注解参数集合。最后通过retrofit.callAdapter(returnType, annotations);创建并返回。
public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {
return nextCallAdapter(null, returnType, annotations);
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
//获取skipPast的位置,skpiPost跳过去
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
//通过CallAdapter.Factory的get方法来获取对应的CallAdapter
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
//如果adapter不为null,则返回adapter
if (adapter != null) {
return adapter;
}
}
// 如果遍历了,还是没有合适的,则抛异常
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(callAdapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
最终调用了nextCallAdapter方法 其内部循环callAdapterFactories拿出CallAdapter.Factory并调用其get方法。
如果我们添加了RxJava2CallAdapterFactory就执行RxJava2CallAdapterFactory的get方法创建自己,如果没有添加,就创建系统默认的DefaultCallAdapterFactory。
第二步通过createResponseConverter()创建Converter
private Converter<ResponseBody, T> createResponseConverter() {
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);
}
}
最终也是调了Retrofit中的nextResponseBodyConverter方法
public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {
return nextResponseBodyConverter(null, type, annotations);
}
public <T> Converter<ResponseBody, T> nextResponseBodyConverter(
@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {
checkNotNull(type, "type == null");
checkNotNull(annotations, "annotations == null");
//获取跳过的skipPast对象的位置,然后加1
int start = converterFactories.indexOf(skipPast) + 1;
for (int i = start, count = converterFactories.size(); i < count; i++) {
//获取对应的 Converter.Factory对象,然后调用requestBodyConverter()方法,
Converter<ResponseBody, ?> converter =
converterFactories.get(i).responseBodyConverter(type, annotations, this);
//由于requestBodyConverter()默认是返回null,所以只有重写过才会不为null
if (converter != null) {
//noinspection unchecked
return (Converter<ResponseBody, T>) converter;
}
}
// 如果遍历了,还是没有合适的,则抛异常
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());
}
循环converterFactories拿出我们配置的Converter.Factory,执行其responseBodyConverter方法。我们一开始指定了.addConverterFactory(GsonConverterFactory.create())
所以就是GsonConverterFactory的responseBodyConverter方法来获取GsonConverterFactory实例。
第三步循环方法的注解并解析并检查for(Annotation annotation : methodAnnotations) {parseMethodAnnotation(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)给相对地址relativeUrl和相对地址的name,relativeUrlParamNames赋值。
第四步循环解析参数的注解
具体解析方法通过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;
}
可以看到parseParameter方法内部其实也是遍历这个参数的所有注解,然后通过调用parseParameterAnnotation()方法来解析每一个注解
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();
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()
+ "<String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter<?, String> converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.Query<>(name, converter, encoded).iterable();
} 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 QueryName) {
QueryName query = (QueryName) annotation;
boolean encoded = query.encoded();
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()
+ "<String>)");
}
ParameterizedType parameterizedType = (ParameterizedType) type;
Type iterableType = Utils.getParameterUpperBound(0, parameterizedType);
Converter<?, String> converter =
retrofit.stringConverter(iterableType, annotations);
return new ParameterHandler.QueryName<>(converter, encoded).iterable();
} else if (rawParameterType.isArray()) {
Class<?> arrayComponentType = boxIfPrimitive(rawParameterType.getComponentType());
Converter<?, String> converter =
retrofit.stringConverter(arrayComponentType, annotations);
return new ParameterHandler.QueryName<>(converter, encoded).array();
} else {
Converter<?, String> converter =
retrofit.stringConverter(type, annotations);
return new ParameterHandler.QueryName<>(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<String, String>)");
}
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()
+ "<String>)");
}
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<String, String>)");
}
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()
+ "<String>)");
}
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<String, String>)");
}
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()
+ "<String>)");
}
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()
+ "<String>)");
}
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<String, String>)");
}
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<Part> or a different value type instead.");
}
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.
}
这个方法特别长,主要是需要判断的注解的类型非常多。根据不同的注解来生成对应的不同的ParameterHandler的静态内部类对象。最终保存在ServiceMethod的数组parameterHandlers中。
第五步,判断一些约束之后,开始创建ServiceMethod对象
return new ServiceMethod<>(this);
这就分析完了eagerlyValidateMethods()方法。它主要是通过ServiceMethod的builder来创建ServiceMethod对象并对其内部参数赋值。
下面开始看Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
方法
可以看到,这里运用了java的动态代理,Proxy.newProxyInstance方法返回的就是我们的接口GitHubService的代理对象。 invoke方法就是接口方法的具体实现,invoke()方法里面的method为具体的方法(在demo就是GitHubService 中的 listRepos方法);args是该方法的参数。
看看InvocationHandler()中
(1)判断是不是Object的方法,如果是直接执行invoke方法
(2)看看是不是平台默认的方法。这个永远返回false不执行
(3)调用loadServiceMethod()方法解析数据,如果缓存中有,直接取出,没有就创建。跟eagerlyValidateMethods()中的是一个方法。loadServiceMethod()方法主要是吧将一个接口的方方法的调用适配成一个HTTP的Call。
(4)用serviceMethod和args作为参数,构造一个OkHttpCall对象。OkHttpCall是retrofit2.Call接口的实现类,主要用来执行同步和异步的网络请求。
(5)调用serviceMethod的callAdapter对象的adapt(OkHttpCall)方法获取一个代理实现类的对象并返回。比如上面的例子返回GitHubService对象,如果使用rxjava可能返回Observable对象。
好长啊,创建工作完成,下一篇在看执行工作
总结:
这一篇主要分析了Retrofit的创建和Service的创建。Retrofit的创建主要是初始化一系列的参数,如基url,请求和响应的转换器工厂集合,请求Call的适配器工厂集合,回调执行器,网络请求工厂等。
Service的创建通过Retrofit中的create方法,这是Retrofit的核心方法之一,通过动态代理,把我们定义的service接口,转化成为可执行的OkHttpCall。最后通过serviceMethod的callAdapter对象的adapt(OkHttpCall)方法适配成一个我们想要的代理实现类的对象并返回。