目的:分析使用Retorfit发起一个网络请求的总过程。
首先看一下项目中Retrofit的构建过程:
public static Api getNetService() {
if (commmonApi == null) {
Gson gson = new GsonBuilder().setLenient().create();
commmonApi = new Retrofit.Builder().client(OkHttpClientUtils.getOkHttpClient())
.baseUrl(HttpConfig.BASE_URL) //请求服务器地址
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build().create(Api.class);
}
return commmonApi;
}
使用的时候,声明一个借口类用来存放每个请求的信息:
Api.class
public interface Api {
@FormUrlEncoded
@POST("v1/search.do") //具体接口地址
Observable<BaseBean<SearchResultBean>> search(@FieldMap Map<String, String> paramMap);
}
发起搜索请求示例(真实项目肯定会进行封装,此处只是示例):
ParamMap paramMap = new ParamMap();
paramMap.put("pageNo", pageNo + "");
paramMap.put("pageSize", pageSize + "");
NetService.getNetService().search(paramMap)
.delay(delayMillis, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<BaseBean<T>>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull BaseBean<T> tBaseBean) {
}
@Override
public void onError(@NonNull Throwable e) {
}
@Override
public void onComplete() {
}
});
首先第一个问题:NetService.getNetService().search(paramMap)
是如何进行调用的,明明声明的只是一个接口!
只能从Retrofit的构建过程入手了:
new Retrofit.Builder().client(OkHttpClientUtils.getOkHttpClient())
.baseUrl(HttpConfig.BASE_URL) //请求服务器地址
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build().create(Api.class);
前边都是通过Retrofit的构建者来配置参数,create才是真正创建并返回Api对象的方法:
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 {
//1.获取该方法的所有必要信息
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//2. 封装请求信息与参数
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//3.发起调用
return serviceMethod.adapt(okHttpCall);
}
});
}
核心代码如上,恍然大悟,原来是通过动态代理来进行反射调用的。其中的method就是发起的请求方法search,args就是被@FieldMap
注解修饰的Map参数。
简单的三步调用,下文主要就是围绕着1,3注释代码语句展开。
在展开之前,首先要明确几个大块的作用【由于篇幅时间有限,该文只分析主干流程,具体细节不再展开,沉迷于细节也容易影响进度】
-
CallAdapter
:适配器,通过.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
传入,主要作用就是兼容Android、Rxjava、Guava和java8这4个平台或类库,默认返回的就是Call,使用的应该就是转换器模式。此处传入的是RxJava2CallAdapter
,它后续的作用就是讲OkHttp返回的Call<T> 转换为 Observable<T>。该适配器最终会传递给ServiceMethod
类中的callAdapter
变量。 -
Converter
:转换器,通过.addConverterFactory(GsonConverterFactory.create(new Gson()))
传入,作用就是对OkHttp请求的结果Response
的body进行解析,根据不同的返回内容使用不同的转换器,此处返回的内容是json格式,所以通过Gson来转换为对应的Bean实体类。该转换器最终会传递给ServiceMethod中的responseConverter
变量。 -
responseType
:返回类型,此处为BaseBean<SearchResultBean>
,也是ServiceMethod
中的一个变量。
上边的3个对象都是ServiceMethod中的成员变量。知道了这3个变量的作用,我们就开始分析第一行注释的代码:
//1.获取该方法的所有必要信息
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) 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) {
//如果没有命中缓存,则通过builder创建一个
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
build()方法:
public ServiceMethod build() {
//通过方法返回参数类型获取对应的适配器,此处为RxJava2CallAdapter
callAdapter = createCallAdapter();
//获取返回类型
responseType = callAdapter.responseType();
//获取Response的解析转换器,此处为GsonResponseBodyConverter
responseConverter = createResponseConverter();
//解析方法注解获取信息,如POST/GET,请求地址,isMultipart等
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
//处理参数
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler<?>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
return new ServiceMethod<>(this);
}
方法说明:
- 生成
callAdapter
,根据返回类型寻找最适合的适配器。 - 获取返回类型
responseType
,在接收到结果时,需要借助转换器将字符流转换成对应的Bean。 - 生成结果转换器,在收到Response时,对内容进行转换。
- 其他:获取该请求的
relativeUrl
,因为在创建Retrofit的时候传入了BASE_URL。等等。
ok,第一行代码大概解释完毕,看第二行代码:
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
/**OKHttpCall类**/
OkHttpCall(ServiceMethod<T, ?> serviceMethod, @Nullable Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
将请求接口信息以及参数封装到OKHttpCall
中,OKHttpCall是真正的请求发起者。第二行不做过多解释,看第三行:
//3.发起调用
return serviceMethod.adapt(okHttpCall);
进入ServiceMethod.adapt方法:
T adapt(Call<R> call) {
return callAdapter.adapt(call);
}
最终调用的是 callAdapter.adapt(call);
,上边分析过callAdapter
本质是RxJava2CallAdapter
,因此最终的实现是RxJava2CallAdapter
中的adapt
方法:
@Override public Object adapt(Call<R> call) {
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;
}
...
return observable;
}
其他情况不再分析,根据调试(接口返回的内容也都存放在body中),结果返回的就是new BodyObservable<>(new CallExecuteObservable<>(call));
,典型的代理模式【or 包装者模式?】。
分析到这儿,起码明白了一件事情:我们在Api
接口类中定义的接口的返回类型就是BodyObservable
,该类源码如下:
final class BodyObservable<T> extends Observable<T> {
private final Observable<Response<T>> upstream;
BodyObservable(Observable<Response<T>> upstream) {
this.upstream = upstream;
}
//外部发起订阅时,最终对走该方法
@Override protected void subscribeActual(Observer<? super T> observer) {
upstream.subscribe(new BodyObserver<T>(observer));
}
private static class BodyObserver<R> implements Observer<Response<R>> {
private final Observer<? super R> observer;
private boolean terminated;
//项目中自己定义的observer,对其进行了代理
BodyObserver(Observer<? super R> observer) {
this.observer = observer;
}
@Override public void onSubscribe(Disposable disposable) {
observer.onSubscribe(disposable);
}
@Override public void onNext(Response<R> response) {
if (response.isSuccessful()) {
observer.onNext(response.body());
} else {
terminated = true;
Throwable t = new HttpException(response);
try {
observer.onError(t);
} catch (Throwable inner) {
Exceptions.throwIfFatal(inner);
RxJavaPlugins.onError(new CompositeException(t, inner));
}
}
}
@Override public void onComplete() {
if (!terminated) {
observer.onComplete();
}
}
@Override public void onError(Throwable throwable) {
if (!terminated) {
observer.onError(throwable);
} else {
// This should never happen! onNext handles and forwards errors automatically.
Throwable broken = new AssertionError(
"This should never happen! Report as a bug with the full stacktrace.");
//noinspection UnnecessaryInitCause Two-arg AssertionError constructor is 1.7+ only.
broken.initCause(throwable);
RxJavaPlugins.onError(broken);
}
}
}
}
该类中还有一个内部类:BodyObserver
,构造函数中传入了我们外部自己创建的Observer对象,从而对齐进行了代理【代理模式】,那么最终我们subscribe
的时候,最终会走到还类中的 subscribeActual
方法。
upstream.subscribe(new BodyObserver<T>(observer));
可以看到,最终的生产者是upstream
,该生产者会将事件发送给BodyObserver
的onSubscribe/onNext/onComplete/onError
中。而这个upstream
就是CallExecuteObservable
,因此最终的执行是在CallExecuteObservable
的订阅方法中:
@Override protected void subscribeActual(Observer<? super Response<T>> observer) {
// Since Call is a one-shot type, clone it for each new observer.
Call<T> call = originalCall.clone();
CallDisposable disposable = new CallDisposable(call);
observer.onSubscribe(disposable); //onSubscribe回调给BodyObserver的onSubscribe
boolean terminated = false;
try {
Response<T> response = call.execute(); //####执行真正的网络请求!
if (!disposable.isDisposed()) {
observer.onNext(response); onNext
}
if (!disposable.isDisposed()) {
terminated = true;
observer.onComplete(); //onComplete回调给BodyObserver的onComplete
}
} catch (Throwable t) {
if (terminated) {
RxJavaPlugins.onError(t);
} else if (!disposable.isDisposed()) {
try {
observer.onError(t); //onError回调给BodyObserver的onError
} catch (Throwable inner) {
}
}
}
}
**终于拨开云雾见天明了,终于发现了请求的真正发起处。还记得吗?此处的call就是第二部封装好的OKHttpCall
,因此真正的执行者最终是在OKHttpCall
的execute()
方法:
@Override public Response<T> execute() throws IOException {
okhttp3.Call call;
call = rawCall;
if (call == null) {
try {
call = rawCall = createRawCall();
} catch (IOException | RuntimeException | Error e) {
throw e;
}
}
return parseResponse(call.execute());
}
再坚持一下,看一下这个rawCall
是如何创建的:
/** Builds an HTTP request from method arguments. */
okhttp3.Call toCall(@Nullable Object... args) throws IOException {
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart);
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return callFactory.newCall(requestBuilder.build());
}
最终是把一系列参数传递给callFactory
创建的,而这个callFactory就是我们构建Retrofit的时候传入的
new Retrofit.Builder().client(OkHttpClientUtils.getOkHttpClient())
.baseUrl(HttpConfig.BASE_URL)
.addConverterFactory(ScalarsConverterFactory.create())
...
因此这个callFactory实质就是一个OkHttpClient
,因此这个rawCall
最终的创建是在OKHttpClient
的newCall()方法中:
@Override public Call newCall(Request request) {
return RealCall.newRealCall(this, request, false /* for web socket */);
}
对于okhttp
库中的东西不再分析,此处只需要明白,最终是通过client()
传入的一个客户端来真正处理一个请求,这个客户端可以是okhttp
,也可以是其他的请求库,实质上Retrofit只是一个解耦的模式套路或者代理,使用方便简洁,并没有真正发起请求的功能。
真正的call
已经找到,接下来只需要解析call.execute()
一下返回的Response即可:
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
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();
//...处理异常code
//对原始的body进行加工
ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
//通过responseConverter.convert(body);即GsonResponseBodyConverter进行body与实体的转换
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse); //返回包装的Response给BodyObserver
} catch (RuntimeException e) {
throw e;
}
}
在CallExecuteObservable
类中的subscribeActual
方法中拿到Response
后,随机会将事件发送给BodyObserver
,而BodyObserver
会再次转发给我们自己创建的Observer
。至此,一个完成的网络请求调用就分析完毕。
总结:
1. 构建Retrofit:
- 通过
client(*)
传入真正发起请求的网络客户端,此处为okhttp
。 - 通过
.baseUrl(HttpConfig.BASE_URL)
传入服务器地址。 - 通过
.addConverterFactory(GsonConverterFactory.create(gson))
传入结果转换器,此处转换为json。 - 通过
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
传入类库适配器,此处为RxJava。 - 通过
.create(Api.class);
传入接口定义类。
2. 在.create(Api.class)方法中,动态代理该类中的所有请求方法。
3. 代理拦截到请求做以下处理:
- 根据注解获取请求方法的信息,如
POST/GET
,接口地址,返回类型,请求参数Map等信息。 - 根据返回参数来确定转换器,此处转换为
Observable<T>
- 将所有请求信息封装到
OkHttpCall
类中
网友评论