zoukankan      html  css  js  c++  java
  • Retrofit2的GsonConverterFactory.create()和RxJava2CallAdapterFactory.create()的实现过程以及执行过程

    一概述

      上一节分析了retrofit2从创建到执行的完整流程,本节分析一下两个非常重要的功能。数据转换器的实现以及网络请求适配器的实现。

    二、GsonConvertFactory.create()数据转换器的实现过程以及执行过程

      我们先看下GsonConvertFactory.crete()的源代码,此类在retrofit-converters插件中

    public final class GsonConverterFactory extends Converter.Factory {
      //创建GsonConverterFactory对象
      public static GsonConverterFactory create() {
        return create(new Gson());
      }
    
      @SuppressWarnings("ConstantConditions") // Guarding public API nullability.
      public static GsonConverterFactory create(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        return new GsonConverterFactory(gson);
      }
    
      private final Gson gson;
    
      private GsonConverterFactory(Gson gson) {
        this.gson = gson;
      }
      //将请求结果的body进行转换
      @Override
      public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
          Retrofit retrofit) {
        //这里的TypeAdapter是Gson中用来做序列化和反序列化用的
        //其中TypeToken.get(type)是用来获取一个类类型
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
      //最后返回一个jsonResponse对象做解析工作 return new GsonResponseBodyConverter<>(gson, adapter); } //转换请求结果的body @Override public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonRequestBodyConverter<>(gson, adapter); } }

      我们看一下GsonResponseBodyConverter的源代码,看看其都干了什么事情。

    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;
      }
      //这里的convert方法是Converter接口中定义的convert
      @Override public T convert(ResponseBody value) throws IOException {
        //创建一个JsonReader对象,jsonReader是gson中的类供TypeAdapter序列化以及反序列化时使用的。
        JsonReader jsonReader = gson.newJsonReader(value.charStream());
        try {
          //通过TypeAdapter把读取到的对象转换为泛型
          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();
        }
      }
    }

    看下GsonRequestBodyConverter类

    final class GsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
      private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
      private static final Charset UTF_8 = Charset.forName("UTF-8");
    
      private final Gson gson;
      private final TypeAdapter<T> adapter;
    
      GsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
      }
      //实现Converter接口的convert方法
      @Override public RequestBody convert(T value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        //创建一个jsonwriter
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        //把http请求信息进行序列化
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        //然后把序列化后的结果放到RequestBody中
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
      }

      

    看下Converter.Factroy的源代码,Converter是一个接口,Factory是其内部抽象类。其中定义了各种类型转换的接口。

    //数据转换接口
    public interface Converter<F, T> {
      //数据转换接口 @Nullable T convert(F value) throws IOException; /** Creates {@link Converter} instances based on a type and target usage. */ abstract class Factory { //转换网络请求的返回结果 public @Nullable Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { return null; } //转换请求结果 public @Nullable Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { return null; }

     具体的转化代码也就这么多,都是操作Gson的一系列方法实现的。下面看看GsonConvertFactory是如何在框架中调用的。

     首先要明确一点,既然是响结果转换器,其必定是响应结果前实现回调的,即在Callback回调函数前需要把响应结果给转换后再给Callback。

     上一节我们说过我们生成的Call其实就是DefaultCallAdapterFactory中的ExecutorCallbackCall。然而ExecutorCallbackCall中却没有看得到Converter的身影。ExecutorCallbackCall的源码如下:

    static final class ExecutorCallbackCall<T> implements Call<T> {
        final Executor callbackExecutor;
        final Call<T> delegate;
    
        ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
          this.callbackExecutor = callbackExecutor;
          this.delegate = delegate;
        }
    
        @Override public void enqueue(final Callback<T> callback) {
          Objects.requireNonNull(callback, "callback == null");
    
          delegate.enqueue(new Callback<T>() {
            @Override public void onResponse(Call<T> call, final Response<T> response) {
              callbackExecutor.execute(() -> {
                if (delegate.isCanceled()) {
                  // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                  callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
                } else {
                  callback.onResponse(ExecutorCallbackCall.this, response);
                }
              });
            }
    
            @Override public void onFailure(Call<T> call, final Throwable t) {
              callbackExecutor.execute(() -> callback.onFailure(ExecutorCallbackCall.this, t));
            }
          });
        }
    

      那么接着往上一级目录找找,我们记得在HttpMethodService类的内部有一个invoke方法,其会调用他的实现类CallAdapted类的adapt方法,方法内部会调用DefaultCallAdapterFactory的adapt方法并返回一个ExecutorCallbackCall。并传入一个Call和方法的参数。这个Call的实现类就是HttpCall。你没看错响应结果转换就发生在这个类中。

      @Override final @Nullable ReturnT invoke(Object[] args) {
        Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
        return adapt(call, args);
      }
    
      protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
    
      static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
        private final CallAdapter<ResponseT, ReturnT> callAdapter;
    
        CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
            Converter<ResponseBody, ResponseT> responseConverter,
            CallAdapter<ResponseT, ReturnT> callAdapter) {
          super(requestFactory, callFactory, responseConverter);
          this.callAdapter = callAdapter;
        }
    
        @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
          return callAdapter.adapt(call);
        }
      }
    

     既然已经确定了响应数据转换在HttpCall中发生。那我们看下他具体做了什么事情。

    final class OkHttpCall<T> implements Call<T> {
      private final RequestFactory requestFactory;
      private final Object[] args;
      private final okhttp3.Call.Factory callFactory;
      private final Converter<ResponseBody, T> responseConverter;
    
      private volatile boolean canceled;
    
      @GuardedBy("this")
      private @Nullable okhttp3.Call rawCall;
      @GuardedBy("this") // Either a RuntimeException, non-fatal Error, or IOException.
      private @Nullable Throwable creationFailure;
      @GuardedBy("this")
      private boolean executed;
    
      OkHttpCall(RequestFactory requestFactory, Object[] args,
          okhttp3.Call.Factory callFactory, Converter<ResponseBody, T> responseConverter) {
        this.requestFactory = requestFactory;
        this.args = args;
        this.callFactory = callFactory;
        this.responseConverter = responseConverter;
      }
    

      果然如上面我们分析的那样,HttpCall接收了一个Converter<ResponseBody,T> responseConverter变量。而这个变量就是我们创建retrofit设置的GsonConvertFactory.create()。

      在HttpCall的内部有一个enqueue(callback)方法,其内部会调用parseResponse方法。parseResponse内部会调用convert方法对数据进行转换。这个convert方法就是上面我们提到的GsonResponseBodyConvert。

      HttpCall的enqueue方法

      

    @Override public void enqueue(final Callback<T> callback) {
        ...省略了前面的一些代码
        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) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }
    
            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
    
        ....省略了一些代码
        });
      }
    

      接下来看下parseResponse方法

      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();
    ...省略了一些diamante ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody); try { //在此处做转换操作,这里的responseConverter就是GsonResponseBodyConverter T body = responseConverter.convert(catchingBody); //把body设置进去 return Response.success(body, rawResponse); } catch (RuntimeException e) { catchingBody.throwIfCaught(); throw e; } }

      到这里转换操作就完成了,converter方法的具体实现可以参考上面的GsonResponseBodyConverter源码。

    总结:通过Retrofit设置响应数据转换器GsonConvertFactory.create(),在HttpCall中的enqueue方法中的parseResponse做具体的转换,转换调用的是responseConverter.convert(catchingBody)。其中responseConverter的具体转换操作是在GsonResponseBodyConverter中完成的。好了GsonConvertFactory.create()的源码以及执行流程就这样分析完了。

      ps:补充一下自定义响应数据解析器

      根据上面的分析我们知道创建响应数据解析器的时候解析器需要继承Converter.Factory,并实现Converter.Factory的responseBodyConverter接口。那么我们在自定义响应数据解析器的时候也可以这么干。三部搞定

      1.创建一个XmlConverterFactory并继承Converter.Factory的并实现其responseBodyConverter方法

      2.创建一个具体的解析类,并当做responseBodyConverter的返回值

      3.在retrofit的Builder中注解解析器XmlConverterFactory.create()

      下面是以上三步的示例代码:

    /**
     * xml响应数据解析器
     * create by yangwei
     * on 2020-02-25 20:12
     */
    public class XmlConverterFactory extends Converter.Factory {
        public static XmlConverterFactory create() {
            return new XmlConverterFactory(new Xml());
        }
    
        public static XmlConverterFactory create(Xml xml) {
            return new XmlConverterFactory(xml);
        }
    
        @javax.annotation.Nullable
        @Override
        public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
    
            return new XmlResponseBodyFactory();
        }
    }
    

      

    /**
     * create by yangwei
     * on 2020-02-25 20:16
     */
    public class XmlResponseBodyFactory implements Converter<T, RequestBody> {
        private static final MediaType MEDIA_TYPE = MediaType.get("application/json; charset=UTF-8");
        @javax.annotation.Nullable
        @Override
        public RequestBody convert(T value) throws IOException {
            //此处做具体转换操作
            return RequestBody.create(MEDIA_TYPE,value.bytes);
        }
    }
    

      在Retrofit的Builder中设置其网络请求数据转换器

    Retrofit retrofit = new Retrofit.Builder().
                    baseUrl("http://www.xxxx.com/").//请求地址
                    addConverterFactory(XmlConverterFactory.create()).//自定义xml网络请求结果转换器
                    addCallAdapterFactory(RxJava2CallAdapterFactory.create()).//网络请求适配器
                    build();
    

      自定义的示例代码就写完了,大家在实际的开发过程中可以根据需要自行添加自定义网络请求结果转换器,或者对转换器进行修正。

    三、RxJava2CallAdapterFactory.create()网络请求适配器的实现过程以及执行过程

      上一节分下了默认的请求网络适配器DefaultCallAdapterFactory。让我们先来回顾下它具体是如何工作的。

      首先在retrofit的builder中进行设置,不设置也行默认就是使用的DefaultCallAdapterFactory请求网络适配器。

      在上一节中我们通过retrofit的create方法动态生成了一个接口实例,并调用接口实例的方法返回了一个Call,生成过程是调用loadServiceMethod.invoke(map)方法,ServiceMethod是个抽象类, 其实现类是HttpServiceMethod,在HttpServiceMethod中重新会真正的调用invoke方法,并实例化一个OkHttpCall,通过其HttpServiceMethod的invoke方法,在其方法内部会调用DefaultCallAdapterFactory.adapt方法,DefaultCallAdapterFactory的adapt方法会生成一个ExecutorCallbackCall并返回。

      下面说说RxJava2CallAdapterFactory网络请求适配器是如何实现的,其实原理和前面说的也是差不多的,至少前半部分是相同的。

      先用文本描述一下流程,然后后面说源码的时候就比较清晰了:

      1.在创建Retrofit的时候添加网络请求适配器,即添加RxJava2CallAdapterFactory的能力。

      2.然后在retrofit的中有一个callAdapter方法,其内部会调用nextCallAdapter方法,通过网络适配器工厂集合callAdapterFactories.get(i).get(returntype,annotations,this)方法返回一个适配器,.get(i)方法返回的这个适配器就是我们设置的RxJava2CallAdapterFactory,后面的get(retrunType,annotations,this)方法返回的则是集成CallAdapter接口的RxJava2CallAdapter类。

      3.接着会调用Retrofit的create中的代理方法loadServiceMethod的invoke方法。invoke方法最终是在HttpServiceMethod方法中执行的,并且invoke方法会调用RxJava2CallAdapterFactory中的adapt方法,并传入一个OkHttpCall。在adapt的内部会根据同步调用或者异步调用返回一个ResultObservable的被观察者,ResultObservable里面封装了CallEnqueueObservable或者CallExecuteObservable,而以上两个Observable又封装了OkHttpCall,所以ResultObservable间接持有了OkHttpCall,到此我们需要的Observable也就生成了,其生成步骤可以简化为:retrofit.create->loadServiceMethod.invoke->ServiceMethod.invoke->HttpServiceMethod.invoke->RxJava2CallAdapterFactory.adapt->ResultObservable。

      4.执行过程,当ResultObservable调用其subscribe方法的时候最终会调用其subscribeActual方法,在其subscribeActual内部会调用CallEnqueueObservable的subscribe方法并把ResultObserver当做参数传递过去。在CallEnqueueObservable的subscribe方法中又会调用其自身的subscribeActual方法实现观察者与被观察者的最终绑定,并且会创建一个CallCallback对象,并调用OkHttpCall的enqueue方法执行网络请求,参数就是刚刚创建的CallBbackCall,其持有observer的引用和OkHttpCall的引用。在OkHttpCall的enqueu方法内部会调用网络请求真正的Call(okhttp3.Call)的enqueue方法发起真正的网络请求,并将网络请求的执行结果写入刚刚传进来的CallBackCall的onResponse方法。而CallBackCall的onResponse方法又会回调ResultObservable的onNext方法,而ResultObservable的onNext方法又会调用LambdaObserver的onNext方法,LambdaObserver.onNext方法会最终调用观察这个的回调接口,从而完成整个调用过程。

      a.添加适配器

     addCallAdapterFactory(RxJava2CallAdapterFactory.create()).//网络请求适配器

      b.retrofit中返回CallAdaper网络适配器

    public CallAdapter<?, ?> nextCallAdapter(@Nullable 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;
          }
        }

      c.创建ResultObservable

      HttpServiceMethod中调用invoke方法,并执行RxJava2CallAdapter.adapt(OkHttpCall)

      static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
        private final CallAdapter<ResponseT, ReturnT> callAdapter;
    
        CallAdapted(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
            Converter<ResponseBody, ResponseT> responseConverter,
            CallAdapter<ResponseT, ReturnT> callAdapter) {
          super(requestFactory, callFactory, responseConverter);
          this.callAdapter = callAdapter;
        }
    
        @Override protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
          //返回ResultObservable
          return callAdapter.adapt(call);
        }
      }
    

      以上callAdapter的真正实现是RxJava2CallAdapter,所以我们直接看它的代码

    @Override public Object adapt(Call<R> call) {
        //根据同步或者异步创建Observable
        Observable<Response<R>> responseObservable = isAsync
            ? new CallEnqueueObservable<>(call)
            : new CallExecuteObservable<>(call);
    
            //把创建好的Observable包装秤ResultObservable
        Observable<?> observable;
        if (isResult) {
          observable = new ResultObservable<>(responseObservable);
        } else if (isBody) {
          observable = new BodyObservable<>(responseObservable);
        } else {
          observable = responseObservable;
        }
    

      到此处ResultObservable已经创建完成了,下面看看其是怎样执行的

      d.执行过程

      执行过程的开始会调动ResultObservable的subscribe对观察者和被观察者进行绑定,其最终会只执行ResultObservable的subscribeActual方法

     @Override protected void subscribeActual(Observer<? super Result<T>> observer) {
        upstream.subscribe(new ResultObserver<T>(observer));
      }
    

      从这段代码中我们可以看穿其仅仅执行了订阅而已,其中upstream指的是CallEnqueuObservable或者CallExecuteObservable,这里的参数中的Observer指的是LambdaObserver。

      我们看下ResultObserver都干了些啥,主要看onNext方法

      private static class ResultObserver<R> implements Observer<Response<R>> {
        private final Observer<? super Result<R>> observer;
    
        ResultObserver(Observer<? super Result<R>> observer) {
          this.observer = observer;
        }
    
        @Override public void onSubscribe(Disposable disposable) {
          observer.onSubscribe(disposable);
        }
    
        @Override public void onNext(Response<R> response) {
          observer.onNext(Result.response(response));
        }
    

      在onNext方法中仅仅是调用了LambdaObserver的onNext方法而已。

    回过头来看EnQueueObservable的subscribe,由于subscribe最终会调用subscribeActual方法,所以我们直接看其这个方法就行了

      @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
        //这里的Call指的是OkHttpCall
        Call<T> call = originalCall.clone();
        //创建一个CallCallback会回调类,并将网络请求call和ResultObserver传递进去
        CallCallback<T> callback = new CallCallback<>(call, observer);
        //绑定
        observer.onSubscribe(callback);
        if (!callback.isDisposed()) {
          //执行OkHttpCall的enqueue方法并把CallCallbac实例传递进去
          call.enqueue(callback);
        }
      }
    

      我们接着看OkHttpCall的enqueue都干了些啥

    @Override public void enqueue(final Callback<T> callback) {
        Objects.requireNonNull(callback, "callback == null");
        okhttp3.Call call;
        ...省略了一些代码
        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) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }
    
            try {
              callback.onResponse(OkHttpCall.this, response);
            } catch (Throwable t) {
              throwIfFatal(t);
              t.printStackTrace(); // TODO this is not great
            }
          }
      ...省略了下面的代码
      }
    

      这个方法非常的明确,其利用okhttp3的Call的enqueu发起真正的网络请求并把回调结果写入CallCallback中的onResponse中。

      在CallCallback的onResponse方法中会调用ResultObserver的onNext方法,并把响应就结果传入

        @Override public void onResponse(Call<T> call, Response<T> response) {
          if (disposed) return;
    
          try {
            observer.onNext(response);
    

      紧接着ResultObserver的onNext方法又会调用LambdaObserver的onNext方法并传入响应结果,再接着LambdaObserver的onNext方法又会调用观察者设置的回调函数。到此为止整个执行过程就已经结束了。

    ps:自定义网络请求适配器的方法和数据转换器的步骤类似,这里简单说一下

      1.首选定义一个继承自CallAdapter.Factory的类并实现其方法,在其方法中返回真正适配的类,即实现了CallAdapter接口的类。

      2.定义一个实现了CallAdapter接口的类,在这个中完成真正的适配

      3.在创建retrofit的时候在其Builder中设置这个适配器即可。

    四、总结

      经过分析GsonConverterFactory和RxJava2CallAdapterFactory相信大家对retrofit的理解又有一些更深的感悟了,实时求实的说多读读开源代码对技能和内功的修炼是非常有帮助的。

  • 相关阅读:
    openssl rsa 加密
    SVN
    day04-drf认证、限流、权限、过滤、排序、分页、异常处理、自动接口文档生成、Xadmin后台管理
    day03-drf视图相关
    day02-序列化与反序列化
    day01-drf引入、序列化反序列化前序
    restFul接口设计规范
    Mysql优化之innodb_buffer_pool_size篇
    Mysql(CAST)和Oracle(to_char)应用
    Mongo和Mysql查看查询任务并终止
  • 原文地址:https://www.cnblogs.com/tony-yang-flutter/p/12364343.html
Copyright © 2011-2022 走看看