写在前面
retrofit源码版本2.4.0
前置知识: Java动态代理
从用法开始
代码来自https://www.jianshu.com/p/021a2c6e128b
public interface RetrofitService {
/**
* 获取快递信息
* Rx方式
*
* @param type 快递类型
* @param postid 快递单号
* @return Observable<PostInfo>
*/
@GET("query")
Observable<PostInfo> getPostInfoRx(@Query("type") String type, @Query("postid") String postid);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.kuaidi100.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
.build();
RetrofitService service = retrofit.create(RetrofitService.class);
Observable<PostInfo> observable = service.getPostInfoRx("yuantong", "11111111111");
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<PostInfo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(PostInfo postInfo) {
Log.i("http返回:", postInfo.toString() + "");
}
});
问题有三个:
- 为什么只是写接口Service就可以实现网络请求, 这个逻辑是怎样的?
- 返回对象是怎么转成Observable的?
- 返回对象ResponseBody怎么通过Gson转成泛型对象的?
源码梳理
Retrofit
Retrofit#create
public <T> T create(final Class<T> service) {
//检查service是否是接口类型, 并且service不允许继承其它接口
Utils.validateServiceInterface(service);
//是否提前加载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) {
//如果调用的是Object中的方法, 则直接调用该方法
return method.invoke(this, args);
}
//是否是平台的默认方法
//Platform是接口, 有Android和Java8两个实现类
//上面的Platform.get()方法会判断当前的系统类型
//之所以这么处理, 是因为像Java8那样, 接口中是支持默认方法的
//如果是默认方法, 就直接调用
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);
//生成OkHttpCall并调用执行
return serviceMethod.adapt(okHttpCall);
}
});
}
这里重点就是最后的三行方法.
Retrofit#loadServiceMethod
//动态代理前面执行的这个方法
//遍历service中的全部public方法执行loadServiceMethod
private void eagerlyValidateMethods(Class<?> service) {
Platform platform = Platform.get();
for (Method method : service.getDeclaredMethods()) {
if (!platform.isDefaultMethod(method)) {
loadServiceMethod(method);
}
}
}
//serviceMethodCache缓存信息
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//serviceMethodCache的类型是Map<Method, ServiceMethod<?, ?>>
//如果已经加载过, 就从serviceMethodCache取出直接返回
//这也就是执行eagerlyValidateMethods的意义
//提前加载
ServiceMethod<?, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
//保证线程按全
//这里是不是很像单例里的双检锁/双重校验锁(DCL)
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//如果没加载过, 就创建ServiceMethod
//ServiceMethod这里就是保存方法的各个信息
result = new ServiceMethod.Builder<>(this, method).build();
//缓存进serviceMethodCache
serviceMethodCache.put(method, result);
}
}
return result;
}
ServiceMethod
ServiceMethod.Builder<>(this, method).build()
Builder(Retrofit retrofit, Method method) {
this.retrofit = retrofit;
this.method = method;
//获取方法的注解信息, 注解可以有多个, 所以是数组
//比如注解@Get @NotNull
this.methodAnnotations = method.getAnnotations();
//方法的参数类型
this.parameterTypes = method.getGenericParameterTypes();
//方法的参数中的注解
this.parameterAnnotationsArray = method.getParameterAnnotations();
}
public ServiceMethod build() {
//获取callAdapter
//注意这个方法, 该方法和问题2有关
callAdapter = createCallAdapter();
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?");
}
//注意这个方法, 该方法和问题3有关
responseConverter = createResponseConverter();
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//...各种检查
//Builder模式
//最终生成ServiceMethod, 将builder中的各个参数保存到ServiceMethod中
return new ServiceMethod<>(this);
}
看到这里我们大概可以看出, 接口Service中的方法信息被一一对应保存在了对应的ServiceMethod中.
ServiceMethod#adapt
现在回到Retrofit#create方法的最后, 我们调用了如下方法
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//这里尤其要注意的是, adapt的参数是Call的实现类, OkHttpCall, 后面还要用到
return serviceMethod.adapt(okHttpCall);
下面我们就来看看 ServiceMethod#adapt
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
ServiceMethod#adapt方法很简单, 就是调用了CallAdapter#adapt, 而CallAdapter是接口, 这个时候我们就需要来看看这个callAdapter到底是谁了
在ServiceMethod.Builder#build方法中, 我们创建了callAdapter
callAdapter = createCallAdapter();
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
//最终, 我们的callAdapter是在retrofit类中获取
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
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");
int start = callAdapterFactories.indexOf(skipPast) + 1;
//遍历callAdapterFactories, 一个一个去找
//找到就返回
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
//...
//如果没找到, 输出异常信息
}
如果我们看一下callAdapterFactories, 就会发现, 这个Map里的值正是我们在创建Retrofit的时候通过retrofit2.Retrofit.Builder#addCallAdapterFactory方法传进去的RxJavaCallAdapterFactory.create(), 该方法创建了RxJavaCallAdapterFactory, 也就是说, 通过retrofit2.adapter.rxjava.RxJavaCallAdapterFactory#get方法, 我们获取到了真正的CallAdapter
RxJavaCallAdapterFactory#get
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
boolean isSingle = rawType == Single.class;
boolean isCompletable = rawType == Completable.class;
//如果方法的返回值类型不是Observable, 也不是Single和Completable
//就返回空
//也就是不由RxJavaCallAdapter处理
if (rawType != Observable.class && !isSingle && !isCompletable) {
return null;
}
//最后, 返回的是RxJavaCallAdapter
if (isCompletable) {
return new RxJavaCallAdapter(Void.class, scheduler, isAsync, false, true, false, true);
}
//...
return new RxJavaCallAdapter(responseType, scheduler, isAsync, isResult, isBody, isSingle,
false);
}
也即是, 真正的CallAdapter其实是RxJavaCallAdapter
RxJavaCallAdapter#adapt
现在我们重新回头来看retrofit2.ServiceMethod#adapt
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
我们知道了这里callAdapter是RxJavaCallAdapter, 参数call是OkHttpCall
所以我们来看RxJavaCallAdapter#adapt
//注意, 这里, 也是问题2的关键
@Override public Object adapt(Call<R> call) {
//如果是异步方法, 就返回CallEnqueueOnSubscribe, 如果是同步, 就返回CallExecuteOnSubscribe
OnSubscribe<Response<R>> callFunc = isAsync
? new CallEnqueueOnSubscribe<>(call)
: new CallExecuteOnSubscribe<>(call);
OnSubscribe<?> func;
if (isResult) {
func = new ResultOnSubscribe<>(callFunc);
} else if (isBody) {
func = new BodyOnSubscribe<>(callFunc);
} else {
func = callFunc;
}
Observable<?> observable = Observable.create(func);
if (scheduler != null) {
observable = observable.subscribeOn(scheduler);
}
if (isSingle) {
return observable.toSingle();
}
if (isCompletable) {
return observable.toCompletable();
}
return observable;
}
final class CallEnqueueOnSubscribe<T> implements OnSubscribe<Response<T>> {
private final Call<T> originalCall;
CallEnqueueOnSubscribe(Call<T> originalCall) {
this.originalCall = originalCall;
}
@Override public void call(Subscriber<? super Response<T>> subscriber) {
// Since Call is a one-shot type, clone it for each new subscriber.
Call<T> call = originalCall.clone();
final CallArbiter<T> arbiter = new CallArbiter<>(call, subscriber);
subscriber.add(arbiter);
subscriber.setProducer(arbiter);
//这里, 执行了OkHttpCall#enqueue, 拿到返回值后, 通过arbiter发射出去
call.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, Response<T> response) {
arbiter.emitResponse(response);
}
@Override public void onFailure(Call<T> call, Throwable t) {
Exceptions.throwIfFatal(t);
arbiter.emitError(t);
}
});
}
}
以异步为例, 如果简单些, 可以如下
Observable.create(new Observable.OnSubscribe<T>() {
@Override
public void call(Subscriber<T> subscriber) {
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
subscriber.onNext(response);
}
@Override
public void onFailure(Call call, Throwable t) {
subscriber.onError(t);
}
});
}
});
到这里, 我们就可以回答问题2了.
Retrofit通过动态代理实现了接口中的方法, 在方法的最后, 使用了RxJavaCallAdapter#adapt方法来获取结果, 而RxJavaCallAdapter#adapt做的也就是通过Observable.create创建Observable, 在调用OkHttpCall#enqueue方法拿到返回的结果后, 通过Observable发射出去, 生成Observable的数据流. 这样就把生成的结果转成了Observable.
在上面的异步方法中, 我们实际上通过retrofit2.Call#enqueue来获取请求结果, 而这里的Call, 实际上是OkHttpCall, 所以, 我们来看下OkHttpCall#enqueue
OkHttpCall
OkHttpCall中有OkHttpCall#enqueue和OkHttpCall#execute, 分别对应异步方法和同步方法
我们这里只说OkHttpCall#enqueue
OkHttpCall#enqueue
//如果callback为空, 抛出异常
checkNotNull(callback, "callback == null");
//...检查各个参数
//这里, 才是真正的调用了Okhttp的enqueue方法
//调用OkHttp的enqueue异步方法, 获取结果
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override public void onFailure(okhttp3.Call call, IOException e) {
callFailure(e);
}
private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
//...
//解析返回结果
//这里也是问题3的关键
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//解析结果
//泛型解析
//这里跟我们创建Retrofit的时候通过addConverterFactory(GsonConverterFactory.create(gson)对应
T body = 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;
}
}
所以, 问题3就是, 在OkHttpCall中, 拿到返回结果后, 将结果交给创建Retrofit的时候通过addConverterFactory(GsonConverterFactory.create(gson)生成的对应的GsonConvert, 转成对应的对象
重新梳理
这里, 我们回国头来重新看
public <T> T create(final Class<T> service) {
//...
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
//...
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.adapt(okHttpCall);
}
});
}
- 首先通过动态代理, 生成对应接口的实现类. 调用接口中的方法时, 执行动态代理的invoke方法
- ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method);
方法, 获取接口中方法的信息(方法返回值类型/注解信息/参数类型/参数注解等) - 创建OkHttpCall(封装Okttp中的Call为OkHttpCall)
- 执行CallAdapter#adapter(这里的CallAdapter实际为RxJavaCallAdapter), 在RxJavaCallAdapter#adapter中执行OkHttpCall#enqueue(以异步为例)执行网络请求, 并用Observable将结果发射出去成为Observable
网友评论