目前Android最流行的http框架莫过于Retrofit + OkHttp的组合了,通过Retrofit我们可以直接将Http请求返回转化成RxJava的Observable, 简直是开发的一大利器!那么下面我们就分析一下Retrofit是怎么将OkHttp的Response转化成Observable的。
首先我们来看一下Retrofit最基本的构建代码:
Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(okHttpClient)
.build()
其中GsonConverterFactory是创建GsonResponseBodyConverter,将http请求结果通过Gson解析成实体类;而RxJava2CallAdapterFactory是创建RxJava2CallAdapter, 将返回结果转化成Observable等。那我们就从这两个地方下手。
- RxJava2CallAdapter的创建:
主要是对returnType的分析,初始化RxJava2CallAdapter需要的构造参数。
关于Java Type,请参考:https://blog.youkuaiyun.com/sinat_29581293/article/details/52227953
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); } ... Type observableType = getParameterUpperBound(0, (ParameterizedType) returnType); Class<?> rawObservableType = getRawType(observableType); if (rawObservableType == Response.class) { ... responseType = getParameterUpperBound(0, (ParameterizedType) observableType); } else if (rawObservableType == Result.class) { ... responseType = getParameterUpperBound(0, (ParameterizedType) observableType); isResult = true; } else { responseType = observableType; isBody = true; } return new RxJava2CallAdapter(responseType, scheduler, isAsync, isResult, isBody, isFlowable, isSingle, isMaybe, false); }
- RxJava2CallAdapter中的转化:
@Override public Object adapt(Call<R> call) { //通过RxJava的订阅来发起请求的执行,在CallEnqueueObservable和CallExecuteObservable中dispose方法中调用了call.cancel(), 因此只要取消了RxJava的订阅就直接取消了okhttp的请求。 Observable<Response<R>> responseObservable = isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call); //对执行结果进行进一步处理,这里的observable就是我们最后返回的。 Observable<?> observable; if (isResult) { //Observable<Result<Entity>> 类型的返回, Result持有OkHttp的Response observable = new ResultObservable<>(responseObservable); } else if (isBody) { //Observable<Entity> 类型的返回 observable = new BodyObservable<>(responseObservable); } else { observable = responseObservable; } //订阅线程的管理,一般使用RxJava管理,这里为null if (scheduler != null) { observable = observable.subscribeOn(scheduler); } //Observable转化成其他的可订阅对象 if (isFlowable) { return observable.toFlowable(BackpressureStrategy.LATEST); } if (isSingle) { return observable.singleOrError(); } if (isMaybe) { return observable.singleElement(); } if (isCompletable) { return observable.ignoreElements(); } return observable; }
CallEnqueueObservable中的执行
@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.onSubscribe(callback); call.enqueue(callback); //发起请求 }
OkHttpCall中的请求
@Override public void enqueue(final Callback<T> callback) { //发起okhttp请求 ... call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException { Response<T> response; try { //Http返回结果解析,快要看到GsonConverterFactory登场了 response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } callSuccess(response); } @Override public void onFailure(okhttp3.Call call, IOException e) { ... } private void callFailure(Throwable e) { ... } private void callSuccess(Response<T> response) { try { //CallEnqueueObservable中的callback callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } }); }
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(); //错误处理 ... ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody); try { //解析http请求返回为具体的实体对象,在这里就会实际调用GsonResponseBodyConverter进行Json解析。 T body = serviceMethod.toResponse(catchingBody); return Response.success(body, rawResponse); } catch (RuntimeException e) { ... } }
接下来,我们看看GsonResponseBodyConverter是如何初始化到serviceMethod中去的。
private Converter<ResponseBody, T> createResponseConverter() { Annotation[] annotations = method.getAnnotations(); try { //还是通过Retrofit类中的responseBodyConverter, 这里会获取method中的注解。 //responseBodyConverter中会调用nextResponseBodyConverter 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); } }
Retrofit类中的nextResponseBodyConverter,根据返回类型和注解匹配对应的Converter,在这里找到GsonConverterFactory并创建GsonResponseBodyConverter
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) { //noinspection unchecked return (Converter<ResponseBody, T>) converter; } } ... }
在加入GsonConverterFactory之前,会先加载一个
BuiltInConverters工厂类,处理requestBodyConverter,来看看BuiltInConverters中responseBodyConverter的实现。
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { if (type == ResponseBody.class) { return Utils.isAnnotationPresent(annotations, Streaming.class) ? StreamingResponseBodyConverter.INSTANCE : BufferingResponseBodyConverter.INSTANCE; } if (type == Void.class) { return VoidResponseBodyConverter.INSTANCE; } return null; }
可以看到,如果想不通过GsonConverter直接返回OkHttp的原始ResponseBody,只需要添加一个@Streaming注解就可以了。
@Steaming
@GET
fun request():Observable<ResponseBody>
到此,整个返回结果的转化流程分析结束,我们来理一下执行的流程:
当你通过发起一个请求时,通过动态代理,找到已经加载过的ServiceMethod, 调用ServiceMethod.callAdapter.adapt(OkHttpCall) ,实际就是调用最开始创建的RxJava2CallAdapter中的adapt,然后创建CallEnqueueObservable,通过RxJava的订阅,发起OkHttp的一个请求,然后通过GsonResponseBodyConverter解析好之后,再创建成返回的Observable对象。