前言
学习Retrofit的源码已经有一段时间了,最近又翻了一遍,然后总结了一下。它里面用到了很多个设计模式,有工厂模式、代理模式、适配器模式等。
mRetorfit.create(Service.clss)
create方法的返回语句如下:
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 {
......
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
使用了动态代理,将每次要执行的Service方法做拦截,然后交给里面的三个语句去执行。
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//从缓存中获取ServiceMethod对象
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//构建ServiceMethod对象,并缓存起来
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
此方法用于获取ServiceMethod对象,首先从缓存中获取,如果找不到则构建一个并且缓存起来。保证每个Service中定义的方法只创建对应一个ServiceMethod对象。
Builder代码比较多,它里面初始化了几个重要的对象:callAdapter、responseConverter、parameterHandlers,并且解析注解,然将这些对象都保存起来,用于创建ServiceMethod对象时进行初始化。
构造函数如下:
ServiceMethod(Builder<R, T> builder) {
this.callFactory = builder.retrofit.callFactory();
this.callAdapter = builder.callAdapter;
this.baseUrl = builder.retrofit.baseUrl();
this.responseConverter = builder.responseConverter;
this.httpMethod = builder.httpMethod;
this.relativeUrl = builder.relativeUrl;
this.headers = builder.headers;
this.contentType = builder.contentType;
this.hasBody = builder.hasBody;
this.isFormEncoded = builder.isFormEncoded;
this.isMultipart = builder.isMultipart;
this.parameterHandlers = builder.parameterHandlers;
}
其中几个比较重要的成员:
OkHttpCall是对OkHttp进行包装的一个类,创建的时候会初始化serviceMethod和参数数组args。同样里面有enqueue方法和execute方法。
它的创建是在ServiceMethod中的createCallAdapter方法中,然后调用以下的语句:
retrofit.callAdapter(returnType, annotations)
也就是根据返回类型和注解,在Retrofit中进行创建:
public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
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;
}
}
......
}
首先进行校验,然后通过工厂类进行获取并返回。结合RxJava,所以使用的是RxJava2CallAdapterFactory ,所以这里获取到的是一个RxJava2CallAdapter对象。
RxJava2CallAdapter#adapt()
@Override public Object adapt(Call<R> call) {
//根据是否同步,创建对应的Observable对象
Observable<Response<R>> responseObservable = isAsync
? new CallEnqueueObservable<>(call)
: new CallExecuteObservable<>(call);
Observable<?> observable;
if (isResult) {
observable = new ResultObservable<>(responseObservable);
} else if (isBody) {
observable = new BodyObservable<>(responseObservable);
} else {
observable = responseObservable;
}
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isFlowable) {
return observable.toFlowable(BackpressureStrategy.LATEST);
}
if (isSingle) {
return observable.singleOrError();
}
if (isMaybe) {
return observable.singleElement();
}
if (isCompletable) {
return observable.ignoreElements();
}
return observable;
}
根据是否同步创建出对应的Observable对象,然后进行返回。
当我们使用结合RxJava时,会在方法返回类型定位Observable,然后调用subscribe传入一个Observer对象,也就是开始订阅;在subscribe方法中,会调用subscribeActual方法并且传入Observer对象,而CallEnqueueObservable和CallExecuteObservable都实现了subscribeActual方法。
CallEnqueueObservable#subscribeActual
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// 由于每个Call只能发起一次请求,所以要克隆出新的Call对象
Call<T> call = originalCall.clone();
CallCallback<T> callback = new CallCallback<>(call, observer);
observer.onSubscribe(callback);
//执行异步请求
call.enqueue(callback);
}
其中的originalCall也就是OkHttpCall,它的enqueue方法里同步语句中有两句重要的代码:
call = rawCall = createRawCall();//1
call.enqueue(...)//2
response = parseResponse(rawResponse);//3
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
serviceMethod通过请求参数和注解等构建一个Request对象,然后通过最开始的callFactory创建Call并返回。
2 . Call发起网络请求,然后将请求结果进行解析
3 . 解析过程通过返回码做进一步的判断,如果响应正常,则会调用serviceMethod.toResponse(catchingBody):
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
toResponse方法调用了Converter对象的convert,对返回数据转换成我们想要的数据格式,比如我们最开始进去的是GsonConverterFactory.create(),则会将返回数据转换成Json格式并返回,除此之外还有XML解析器等。Converter的创建也是根据我们设置的Converter工厂在Retrofit中创建的。
到此基本过了一遍从创建、获取数据、转换数据的流程。
创建Retrofit,
1.1 创建的时候初始化ConverterFactory,它用于将某些数据格式转换为目标类型
1.2 创建CallAdapterFactory,用于将Call转换成目标类型,也就是我们在定义方法的返回类型,默认返回ExecutorCallbackCall
1.3 创建Executor,表示在哪个平台执行,默认是MainThreadExecutor,它会将响应结果的回调发送到主线程中
1.4 创建CallFactory,默认是OkHttpClient,创建OkHttp中的Call
执行方法:每执行一个接口定义的方法都会通过动态代理的方式
2.1 初始化ServiceMethod,首先会从缓存中获取,如果不存在则根据Method创建一个并缓存起来
2.2 创建OkHttpCall
2.3 调用CallAdapter的adapt方法,默认返回的是一个ExecutorCallbackCall,并将OkHttpCall传递进去
2.4 返回代理创建的Call对象
发起网络请求
3.1 enqueue方法会让delegate执行它的enqueue方法,这个delegate是OkHttpCall,在它里面发起网络请求
3.2 OkHttpCall的enqueue方法里面会通过ServiceMethod根据参数和方法注解创建Request,然后通过OkHttpClient创建一个OkHttp的Call对象,然后发起网络请求(getResponseWithInterceptorChain方法)
3.3 获取到响应后,进行解析,如果成功,则通过ServiceMethod进行转换,底层是使用ResponseConverter将响应结果转换成我们的目标类型
3.4 将目标类型实例封装到Response中,并回调到对应平台中(MainThreadExecutor:将回调发送到主线程中执行)