01retrofit---使用retrofit完成一次网络请求方法调用链
发布于 2022年 01月 11日 07:27
一、代码具体调用流程
public class Biz {
public static Single<String> method() {
RespTransformer<String> transformer = RespTransform.newInstance();
return ApiGenerator.createApi(Api.class)
.method()
.compose(transformer)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
}
public class presenter {
public void method() {
Biz.method()
.subscribe(new Consumer<List<Resp>>() {
@Override
public void accept(List<Resp> resps) {
...
}
}, new BaseRespThrowableObserver() {
@Override
public void onV2Error(String code, String errorMsg) {
...
}
}));
}
}
public class ApiGenerator {
public static <S> createApi(Class<S> apiClass) {
// serviceCreator()返回Retrofit实例;
return NetManager.getInstance().serviceCreator().create(apiClass);
}
}
上面就是Retrofit的调用流程, 下面根据这个调用流程来进行分析, Retrofit是如何完成一次网络请求的,
2.1 Retrofit.create()
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@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);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
retrofit使用到动态代理
的技术, 使得不同的接口调用, 最终都走到这里, 进行网络请求.
2.2 Retrofit.loadServiceMethod
Retrofit.loadServiceMethod
--->ServiceMethod.parseAnnotations
--->HttpServiceMethod.parseAnnotations
static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
Retrofit retrofit, Method method, RequestFactory requestFactory) {
boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
boolean continuationWantsResponse = false;
boolean continuationBodyNullable = false;
Annotation[] annotations = method.getAnnotations();
Type adapterType;
adapterType = method.getGenericReturnType();
// 1.获取adapter;
CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit, method, adapterType, annotations);
Type responseType = callAdapter.responseType();
// 2.获取convert;
Converter<ResponseBody, ResponseT> responseConverter = createResponseConverter(retrofit, method, responseType);
okhttp3.Call.Factory callFactory = retrofit.callFactory;
// 3.构建CallAdapter;
return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
}
retrofit的好处, 支持自定义convert与adapter, 默认okhttp只是单纯的网络请求, 与rxjava并没有关系, 但是通过Retrofit可以实现okhttp与rxjava的结合. 贴出来一段代码retrofit如何将okhttp与rxjava结合
2.2.1 自定义Adapter与GsonConvert
public void initRetrofit() {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(/*自定义Gson*/))
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
}
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
public static RxJava2CallAdapterFactory create() {
return new RxJava2CallAdapterFactory(null, false);
}
}
- 初始化Retrofit时, 通过Retrofit对外暴露的接口, 传入自定义的Gson和Adapter, 平时在开发时, 应当注意这个思想, 通过建造者的模式, 将能力以接口的形式对外暴露, 支持用户自定义, 提高了扩展性.
- 同时这里也用到了适配器模式, 之前每次提到适配器模式, 可能都会说ListView与Adapter, 但是ListView代码量比较多, 可能理解起来没有那么容易, 这里就很好理解了, okhttp与rxjava本来是不相干的两个东西, 这里使用适配器模式, 将二者结合起来, 接下来看适配器模式如何将okhttp与rxjava结合.
2.2.2 构建RxJava2CallAdapter
class HttpServiceMethod::createCallAdapter
private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(
Retrofit retrofit, Method method, Type returnType, Annotation[] annotations) {
return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);
}
class Retrofit::callAdapter
public CallAdapter<?, ?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) {
Objects.requireNonNull(returnType, "returnType == null");
Objects.requireNonNull(annotations, "annotations == null");
int start = callAdapterFactories.indexOf(skipPast) + 1;
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
}
class RxJava2CallAdapterFactory::get
@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
Class<?> rawType = getRawType(returnType);
if (rawType == Completable.class) {
// Completable is not parameterized (which is what the rest of this method deals with) so it
// can only be created with a single configuration.
return new RxJava2CallAdapter(Void.class, scheduler, isAsync, false, true, false, false,
false, true);
}
boolean isFlowable = rawType == Flowable.class;
boolean isSingle = rawType == Single.class;
boolean isMaybe = rawType == Maybe.class;
// ...
// 这里为okhttp与rxjava结合做了铺垫
return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable,
isSingle, isMaybe, false);
}
2.2.3 rxjava与okhttp相结合
class CallAdapted::invoke
@Override
final ReturnT invoke(Object[] args) {
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
return adapt(call, args);
}
@Override
protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
// callAdapter指向的是初始化Retrofit中传入的RxJava2CallAdapter
return callAdapter.adapt(call);
}
2.1模块loadServiceMethod
返回CallAdapted对象, 当有网络请求时, 触发CallAdapted.invoke方法的执行
2.2.4 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;
}
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 RxJavaPlugins.onAssembly(observable);
}
- 暴露出来的是Retrofit的接口进行网络请求, 但是通过传入的RxJava2CallAdapter, 将请求交给了rxjava, 然后由rxjava调用okhttp完成网络请求, 并且对结果进行包装, 以rxjava的链式结构进行返回.
三、okhttp端
retrofit端作为网络请求的入口, 将请求权和结果的处理权都交给了rxjava, 实现了rxjava与okhttp的结合.
结合rxjava的源码可知, subsrcibe()会触发CallExecuteObservable.subscribeActual的执行
3.1 CallExecuteObservable.subscribeActual
@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();
//...
Response<T> response = call.execute();
//...
}
3.2 OkHttpCall.execute
@Override
public Response<T> execute() throws IOException {
okhttp3.Call call;
synchronized (this) {
executed = true;
// call = RealCall;
call = getRawCall();
}
return parseResponse(call.execute());
}
- getRawCall流程省略, getRawCall返回RealCall对象.
3.3 RealCall.execute
@Override
protected void execute() {
boolean signalledCallback = false;
transmitter.timeoutEnter();
try {
// 网络请求的处理使用了责任链模式
Response response = getResponseWithInterceptorChain();
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
} finally {
// client指向OkHttpClient, 请求结果进行下发
client.dispatcher().finished(this);
}
}
3.4 RealCall.getResponseWithInterceptorChain
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(new RetryAndFollowUpInterceptor(client));
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
originalRequest, this, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
boolean calledNoMoreExchanges = false;
try {
Response response = chain.proceed(originalRequest);
if (transmitter.isCanceled()) {
closeQuietly(response);
throw new IOException("Canceled");
}
return response;
} catch (IOException e) {
calledNoMoreExchanges = true;
throw transmitter.noMoreExchanges(e);
} finally {
if (!calledNoMoreExchanges) {
transmitter.noMoreExchanges(null);
}
}
}
- 目前来看retrofit的作用相当于是一个配置器, 通过建造者的模式对外提供接口, 使得Gson解析, 结果的处理可以自定义, 将rxjava与okhttp结合起来, 请求最终还是通过OkHttp进行;
- 这里使用 责任链模式 代替了传统的if...else, 在工作中也有借鉴retrofit这个地方的责任链模式, 感觉效果也确实比较好用.