———-继续,这篇分析Retrofit的源码。(真是太懒了)
首先看一下官网的介绍,(官网 在此),官网给的描述是 A type-safe HTTP client for Android and Java,其实也就是对okhttp再次进行了封装,使得开发者更方便的使用网络请求。基本使用如下:
1,先创建一个接口,里面定义了请求方式,地址,返回数据类型,参数。
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
@GET("users/{user}/repos")
Obeserble<List<Repo>> listRepos(@Path("user") String user);
}
2,生成一个Retrofit实例,然后调用create()方法,传入刚才创建的GitHubService 类名。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
3,直接从接口拿到一个Call,当然,这个类型可以是其他类型的。
Call<List<Repo>> repos = service.listRepos("octocat");
基本用法请自行了解,这里我们主要分析源码。
创建Retrofit 实例是一个Builder模式,没什么好说的,需要注意的一点是, 这创建的时间调用了unmodifiableList(),这是Collections类的一个方法,
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
瞄一眼方法描述,Returns an unmodifiable view of the specified list. This method allows modules to provide users with “read-only” access to internal lists. 开头两句是这么写的, 就是说返回一个不可更改的List对象,可以保护创建的对象中的数据只读, 不能更改。之前没遇到过,记录下。
接下来重点(敲黑板!!!)
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.
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.callAdapter.adapt(okHttpCall);
}
});
}
看到了一个返回Proxy,知道这是代理的意思,其实这里用到了动态代理的方法,(有关 动态代理和静态代理的 区别请看 此)。
这里解释下InvocationHandler 中回调invoke方法的参数 。
- Object proxy: 代理对象,不关心这个
- Method method:调用的方法,就是listRepos方法
- Object… args:方法的参数,就是”octocat”
可以知道,
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
都不会执行。
那么接下来我们首先看 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) {
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
这里有Map去缓存ServiceMethod对象,如果有则直接返回,没有就去创建 。
我们看ServiceMethod的构造函数。也是使用了Builder模式 ,
public ServiceMethod build() {
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
responseConverter = createResponseConverter();
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];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
这里删除一些检查的代码,看主要的。
最后调用build();会创建一些初始对象。每一个参数都都会封装到一个ParameterHandler里。
然后new 了一个okhttpCall ,直接调用 serviceMethod.callAdapter.adapt(okHttpCall); 这里的serviceMethod.callAdapte , 就是之前serviceMethod.Builder 中调用createCallAdapter()返回赋值给serviceMethod的成员对象。
这里比较有意思了,
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);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
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);
}
}
看retrofit.callAdapter ,返回到了Retrofit中, 在nextCallAdapter 中有
int start = adapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
遍历adapterFactories,依据刚才在GitHubService 中每个方法的返回值,对应着一个Factory,比如,在Retrofit中Builder的时候默认添加了一个
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
,也就是说当你在初始化Retrofit的时候不去addCallAdapterFactory();默认的返回类型必须是Call。返回其它的类型,在遍历的时候找不到对应的Factory, 会抛异常。
回到serviceMethod.callAdapter.adapt(okHttpCall);
这里的callAdapter 其实默认就是一个ExecutorCallAdapterFactory.get()返回的值 , 我们进入这个类。
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
看Call方法
@Override public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
当我们拿到一个Call 时, 可以去enqueue()(异步),或execute();那么这个Call呢, 其实就是OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
这里的Call了。OkHttpCall我觉得可以当作是适配器模式,可也以做包装设计模式 。
这里面的代码比较简单,直接生成一个Okhttp包的Call,再去调用。
至此,Retrofit 的源码已经分析完,我们只是粗略的过了一下流程,整个Retrofit用到了很多种设计模式,这个我们得好好消化一下。完