转载
Retrofit 核心功能、关键节点
1、Retrofit # create() 动态代理:实现对不同业务的 APIService 聚合统一调用 2、CallAdapterFactory:请求适配工厂,比如,实现 RxJava 的支持 (RxJava2CallAdapter) 3、ConverterFactory:解析工厂,Response 数据解析,转为 JavaBean 4、callFactory:OkHttpClient 就是一个 callFactory的实现类,用于创建 RealCall 对象
执行流程
baseUrlCallAdapterFactoryConverterFactory请求结果数据转换build 生成 Retrofit 对象 网络请求相关方法 缓存中没有该Method对应 ServiceMethod 缓存中已存在 同步请求 异步请求 Retrofit # Builder Retrofit 定义请求API 接口 APIService 获取API实例 retrofit#create 传入 APIService.class 对API中所有方法实现动态代理 调用API实例方法 apiService # requestData 触发动态代理 调用 Retrofit # loadServiceMethod 传入 Method对象 获取 ServiceMethod 从缓存同步获取ServiceMethod 同步创建 ServiceMethod 后放入缓存 返回 ServiceMethod 实例 一个 ServiceMethod 对象 APIService 的一个方法缓存目的 同一个 API 的同一个方法 只会创建一次 ServiceMethod callFactory请求工厂 创建 Okhttp # RealCall 对象 callAdapter 请求适配器 对 RealCall的包装 responseConverter 数据解析 parameterHandlers 解析参数注解 获取参数信息 ServiceMethod # invoke 传入 方法参数 创建 retrofit2.OkHttpCall 调用 ServiceMethod # adapt 传入 OkHttpCall 和 参数 callAdapter.adapt Retrofit#Builder 构建时传入 RxJava2CallAdapter 包装 RealCall 返回 Observable 对象默认 DefaultCallAdapterFactory # CallAdapter OkHttpCall # execute 同步请求 callFactory.newCall 创建 RealCall Okhttp3 # Call # execute 执行 Okhttp 同步请求流程 OkHttpCall # parseResponse 解析 Response OkHttpCall # enqueue 异步请求 callFactory.newCall 创建 RealCall Okhttp3 # Call # enqueue 执行OkHttp 异步请求流程 responseConverter # convert 解析 RsponseBody 转为对象(1) ServiceMethod<T> 把接口方法的调用转为一次 HTTP 调用 一个 ServiceMethod 对象对应于一个 API interface 的一个方法 loadServiceMethod(method) 方法负责加载 ServiceMethod。
ServiceMethod loadServiceMethod(Method method) { ServiceMethod result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder(this, method).build(); serviceMethodCache.put(method, result); } } return result; }实现了缓存逻辑,同一个 API 的同一个方法,只会创建一次。 我们每次获取 API 实例都是传入的 class 对象,而 class 对象是进程内单例的, 所以获取到它的同一个方法 Method 实例也是单例的,所以这里的缓存是有效的
final class ServiceMethod<R, T> { private final okhttp3.Call.Factory callFactory; private final CallAdapter<R, T> callAdapter; private final Converter<ResponseBody, R> responseConverter; private final ParameterHandler<?>[] parameterHandlers; ... ServiceMethod(Builder<R, T> builder) { this.callFactory = builder.retrofit.callFactory(); this.callAdapter = builder.callAdapter; this.responseConverter = builder.responseConverter; this.parameterHandlers = builder.parameterHandlers; ... } }1)okhttp3.Call.Factory callFactory 请求工厂
负责创建 HTTP 请求,HTTP 请求被抽象为了 okhttp3.Call 类, 它表示一个已经准备好,可以随时执行的 HTTP 请求; OkHttpClient 实现了这个接口。
在构造Retrofit 对象时,可以指定 callFactory,如果不指定,将默认设置为一个 okhttp3.OkHttpClient
2)CallAdapter<R, T> callAdapter 请求适配器 把 retrofit2.Call 转为 T。
(注意和 okhttp3.Call 区分开来,retrofit2.Call 表示的是对一个 Retrofit 方法的调用), 这个过程会发送一个 HTTP 请求,拿到服务器返回的数据(通过 okhttp3.Call 实现), 并把数据转换为声明的 T 类型对象(通过 Converter<F, T> 实现);
final class ServiceMethod<R, T> { private CallAdapter<T, R> createCallAdapter() { Type returnType = method.getGenericReturnType(); // 省略检查性代码 ... Annotation[] annotations = method.getAnnotations(); try { 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); } } } public final class Retrofit { /* 这个工厂列表我们可以在构造 Retrofit 对象时进行添加 * Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addCallAdapterFactory() .build() */ final List<CallAdapter.Factory> callAdapterFactories; public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) { return nextCallAdapter(null, returnType, annotations); } /** * 遍历一个 CallAdapter.Factory 列表,让工厂们提供, * 如果最终没有工厂能(根据 returnType 和 annotations)提供需要的 CallAdapter,那将抛出异常。 */ public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { ... 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; } } ... throw new IllegalArgumentException(...); } }3)responseConverter 是 Converter<ResponseBody, T> 类型, 负责把服务器返回的数据(JSON、XML、二进制或者其他格式,由 ResponseBody 封装)转化为 T 类型的对象;
final class ServiceMethod<R, T> { private Converter<ResponseBody, T> createResponseConverter() { Annotation[] annotations = method.getAnnotations(); try { return retrofit.responseBodyConverter(responseType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create converter for %s", responseType); } } } public final class Retrofit { /* 这个工厂列表我们可以在构造 Retrofit 对象时进行添加 * Retrofit retrofit = new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create()) .build(); */ final List<Converter.Factory> converterFactories; public <T> Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) { return nextResponseBodyConverter(null, type, annotations); } /** * 遍历 Converter.Factory 列表,看看有没有工厂能够提供需要的 responseBodyConverter。 * 工厂列表可以在构造 Retrofit 对象时进行添加。 */ public <T> Converter<ResponseBody, T> nextResponseBodyConverter(@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) { ... int start = converterFactories.indexOf(skipPast) + 1; for (int i = start, count = converterFactories.size(); i < count; i++) { Converter<ResponseBody, ?> converter = converterFactories.get(i).responseBodyConverter(type, annotations, this); if (converter != null) { return (Converter<ResponseBody, T>) converter; } } ... throw new IllegalArgumentException(...); } }4)parameterHandlers 则负责解析 API 定义时每个方法的参数,并在构造 HTTP 请求时设置参数;
i.每个参数都会有一个 ParameterHandler,由 ServiceMethod#parseParameter() 方法负责创建 每个参数的信息解析出来后都会包装成一个 ParameterHandler 对象。
ii.ServiceMethod#parseParameter() 其主要内容就是解析每个参数使用的注解类型(诸如 Path,Query,Field 等), 对每种类型进行单独的处理。
构造 HTTP 请求时,我们传递的参数都是字符串, 那 Retrofit 是如何把我们传递的各种参数都转化为 String 的呢? 还是由 Retrofit 类提供 converter!
Converter.Factory 除了提供上一小节提到的 responseBodyConverter, 还提供 requestBodyConverter 和 stringConverter,API 方法中除了 @Body 和 @Part 类型的参数, 都利用 stringConverter 进行转换, 而 @Body 和 @Part 类型的参数则利用 requestBodyConverter 进行转换。
这三种 converter 都是通过“询问”工厂列表进行提供, 而工厂列表我们可以在构造 Retrofit 对象时进行添加。
(2)工厂让各个模块得以高度解耦
各个工厂负责不同的功能,而Retrofit 值负责向工厂提供用于决策的信息,例如参数/返回值类型/注解等。
OkHttpCall内部封装了 同步/异步网络请求
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
OkHttpCall 实现了 retrofit2.Call,我们通常会使用它的 execute() 和 enqueue(Callback callback) 接口。 前者用于同步执行 HTTP 请求,后者用于异步执行。
final class OkHttpCall<T> implements Call<T> { //1)同步请求 @Override public Response<T> execute() throws IOException { okhttp3.Call call; synchronized (this) { //【1】创建 okhttp3.Call,包括构造参数; call = rawCall; if (call == null) { try { call = rawCall = createRawCall(); } catch (IOException | RuntimeException e) { creationFailure = e; throw e; } } } //【2】call.execute() 同步执行网络请求,返回 Response 对象 //【3】解析网络请求返回的数据; return parseResponse(call.execute()); } // callFactory 就是 OkHttpClient 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; } //解析网络请求返回的数据 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(); if (code < 200 || code >= 300) { // ...返回错误 } if (code == 204 || code == 205) { return Response.success(null, rawResponse); } ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { // 内部调用 responseConverter.convert(body) 把body 转成 T T body = serviceMethod.toResponse(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { // ...异常处理 } } //2)异步请求 @Override public void enqueue(final Callback<T> callback) { ... okhttp3.Call call; Throwable failure; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; //【1】创建 okhttp3.Call,包括构造参数; call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { call = rawCall = createRawCall(); } catch (Throwable t) { throwIfFatal(t); failure = creationFailure = t; } } } if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } //【2】调用 okhttp3.Call 的 enqueue() 方法,执行异步请求 call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) { Response<T> response; try { //【3】解析响应数据 response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } ... }); } }CallAdapter#adapt(Call call) 函数负责把 retrofit2.Call 转为 T。 这里 T 当然可以就是 retrofit2.Call,这时我们直接返回参数就可以了, 实际上这正是 DefaultCallAdapterFactory 创建的 CallAdapter 的行为。 至于其他类型的工厂返回的 CallAdapter 的行为,这里暂且不表,后面再单独分析。
Retrofit中 CallAdapter 的适配器模式
retrofit 模块内置了 DefaultCallAdapterFactory 和 ExecutorCallAdapterFactory, 它们都适用于 API 方法得到的类型为 retrofit2.Call 的情形,
1)DefaultCallAdapterFactory 生产的 adapter 啥也不做,直接把参数返回,
2)ExecutorCallAdapterFactory 生产的 adapter 则会在异步调用时在指定的 Executor 上执行回调。
异步请求结束后,会在 callbackExecutor 回调结果 ExecutorCallAdapterFactory(Executor callbackExecutor)
3)RxJavaCallAdapterFactory
RxJava2CallAdapterFactory#get 方法中对返回值的类型进行了检查, 只支持 rx.Single,rx.Flowable,rx.Maybe,rx.Completable 和 rx.Observable, 然后返回 RxJava2CallAdapter 对象。
如果 Retrofit 中设置了 RxJavaCallAdapterFactory,那么 Retrofit的 CallAdapter 就是 RxJava2CallAdapter
RxJava2CallAdapter.adapt() 会返回一个 Obserable对象。 Observable.subscribe,触发 API 调用的执行;
final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> { @Override public Object adapt(Call<R> call) { Observable<Response<R>> responseObservable = isAsync //异步请求,创建 CallEnqueueObservable ? new CallEnqueueObservable<>(call) //同步请求,创建 CallExecuteObservable : 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; } }执行网络请求时,会调用 ServiceMethod.adapt() -> RxJava2CallAdapter.adapt()
i.异步请求 CallEnqueueObservable
final class CallEnqueueObservable<T> extends Observable<Response<T>> { private final Call<T> originalCall; CallEnqueueObservable(Call<T> originalCall) { this.originalCall = originalCall; } @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(); CallCallback<T> callback = new CallCallback<>(call, observer); /* * observer在 callback构造函数中已经把 observer传入,并且在 callback的对应函数中做了回调 * 调用observer#onSubscribe(@NonNull Disposable d)方法,通知应用层要开始请求了 */ observer.onSubscribe(callback); call.enqueue(callback); } private static final class CallCallback<T> implements Disposable, Callback<T> { private final Call<?> call; private final Observer<? super Response<T>> observer; private volatile boolean disposed; boolean terminated = false; CallCallback(Call<?> call, Observer<? super Response<T>> observer) { this.call = call; this.observer = observer; } @Override public void onResponse(Call<T> call, Response<T> response) { ... observer.onNext(response); ... observer.onComplete(); ... observer.onError(t); } @Override public void onFailure(Call<T> call, Throwable t) { ... observer.onError(t); ... } ... } }ii.同步请求 CallExecuteObservable
final class CallExecuteObservable<T> extends Observable<Response<T>> { private final Call<T> originalCall; CallExecuteObservable(Call<T> originalCall) { this.originalCall = originalCall; } @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); boolean terminated = false; try { //调用 retrofit.OkHttpCall.execute()会调用 OkHttp.Call.execute()执行同步请求 Response<T> response = call.execute(); if (!disposable.isDisposed()) { observer.onNext(response); } if (!disposable.isDisposed()) { terminated = true; observer.onComplete(); } } catch (Throwable t) { Exceptions.throwIfFatal(t); if (terminated) { RxJavaPlugins.onError(t); } else if (!disposable.isDisposed()) { try { observer.onError(t); } catch (Throwable inner) { Exceptions.throwIfFatal(inner); RxJavaPlugins.onError(new CompositeException(t, inner)); } } } } private static final class CallDisposable implements Disposable { private final Call<?> call; private volatile boolean disposed; CallDisposable(Call<?> call) { this.call = call; } @Override public void dispose() { disposed = true; call.cancel(); } @Override public boolean isDisposed() { return disposed; } } }GsonConverterFactory 把网络请求返回的 Response 转成 T 对象
public final class GsonConverterFactory extends Converter.Factory { @Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonResponseBodyConverter<>(gson, adapter); } } final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> { private final Gson gson; private final TypeAdapter<T> adapter; GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; } @Override public T convert(ResponseBody value) throws IOException { JsonReader jsonReader = gson.newJsonReader(value.charStream()); try { T result = adapter.read(jsonReader); if (jsonReader.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed."); } return result; } finally { value.close(); } } }工厂模式,方便使用者根据需要自定义实现对应功能
推荐阅读: 拆轮子系列:拆Retrofit https://blog.piasy.com/2016/06/25/Understand-Retrofit/index.html
