美文网首页
retrofit的CallAdapter和GsonConvert

retrofit的CallAdapter和GsonConvert

作者: 慕尼黑凌晨四点 | 来源:发表于2022-02-27 18:33 被阅读0次

    刚开始学Retrofit的时候对CallAdapterFactory和GsonConvert总是搞不清楚,现在总结下:

    CallAdapterFactory

    DefaultCallAdapterFactory

    CallAdapterFactory生产CallAdapter,CallAdapter的作用是将网络返回的数据进行拿到的时候,我们在这里还有一次机会对数据进行处理(数据处理或线程处理)。
    Retrofit写了一个默认的CallAdapter,该adapter帮我们切换了线程,切到了Android的主线程。

    具体是DefaultCallAdapterFactory.get()返回的那个匿名类:

    final class DefaultCallAdapterFactory extends CallAdapter.Factory {
      private final @Nullable Executor callbackExecutor;
    
      DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
        this.callbackExecutor = callbackExecutor;
      }
    
      @Override
      public @Nullable CallAdapter<?, ?> get(
        ...
        final Executor executor =
            Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
                ? null
                : callbackExecutor;
    
        //就是下面这个!
        return new CallAdapter<Object, Call<?>>() {
          @Override
          public Type responseType() {
            return responseType;
          }
    
          @Override
          public Call<Object> adapt(Call<Object> call) {
            return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
          }
        };
          
      }
     ...
    }
    

    具体retrofit如何使用这个类的:

    retrofit在create()方法的时候通过动态代理生成了实现我们api接口的类,所以会统一调到代理方法loadServiceMethod(method).invoke(args)

    loadServiceMethod方法返回了一个CallAdapted对象。

    CallAdapted 继承 HttpServiceMethod 继承 ServiceMethod。

    但传入的这个CallAdapted其实也是个壳儿,因为CallAdapted内部持有一个callAdapter,需要在构造方法中传入。

    而这次loadServiceMethod中传入的call Adapter就是从默认的callAdapterFactory是DefaultCallAdapterFactory,它的get方法返回的就是上面写的默认的CallAdapter(匿名内部类)。

    invoke方法在HttpServiceMethod中:

    @Override
    final @Nullable ReturnT invoke(Object[] args) {
      Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
      return adapt(call, args);
    }
    

    adapt方法在CallAdapted自己里面:

    static final class CallAdapted<ResponseT, ReturnT> extends HttpServiceMethod<ResponseT, ReturnT> {
        private final CallAdapter<ResponseT, ReturnT> callAdapter;
    
        CallAdapted(...,CallAdapter<ResponseT, ReturnT> callAdapter) {
            super(...);
            this.callAdapter = callAdapter;
        }
    
        @Override
        protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
            return callAdapter.adapt(call);
        }
    }
    

    所以调用的就是外面传进来的adapterd.adapt方法。返回值是 new ExecutorCallbackCall<>(executor, call)

    executor是构造方法中传入的callbackExecutor,实际在Android中是MainThreadExecutor,原来就是主线程。

    static final class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());
    
      @Override
      public void execute(Runnable r) {
        handler.post(r);
      }
    }
    

    而具体返回的ExecutorCallbackCall 和 原先的Call比起来,也就是切了个线程的意思:

    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) {
        delegate.enqueue(
            new Callback<T>() {
              @Override
              public void onResponse(Call<T> call, final Response<T> response) {
                callbackExecutor.execute(
                    () -> {
                      if (delegate.isCanceled()) {
                        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));
              }
            });
      }
      ...
    }
    

    RxJava2CallAdapterFactory

    所以直接看RxJava2CallAdapterFactory的get方法返回就好了,返回的是个RxJava2CallAdapter:

    final class RxJava2CallAdapter<R> implements CallAdapter<R, Object> {
      private final Type responseType;
      private final @Nullable Scheduler scheduler;
      private final boolean isAsync;
      private final boolean isResult;
      private final boolean isBody;
      private final boolean isFlowable;
      private final boolean isSingle;
      private final boolean isMaybe;
      private final boolean isCompletable;
    
      RxJava2CallAdapter(Type responseType, @Nullable Scheduler scheduler, boolean isAsync,
          boolean isResult, boolean isBody, boolean isFlowable, boolean isSingle, boolean isMaybe,
          boolean isCompletable) {
        this.responseType = responseType;
        this.scheduler = scheduler;
        this.isAsync = isAsync;
        this.isResult = isResult;
        this.isBody = isBody;
        this.isFlowable = isFlowable;
        this.isSingle = isSingle;
        this.isMaybe = isMaybe;
        this.isCompletable = isCompletable;
      }
    
      @Override public Type responseType() {
        return responseType;
      }
    
      //所以直接看adapt方法就好了,就是返回的call改成RxJava里面的流了
      @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 observable;
      }
    }
    

    其实retrofit自带还有一个CompletableFutureCallAdapterFactory 和 CompletableFutureCallAdapterFactory,对应的是java8里面的流,有兴趣可以看下。

    GsonConvert

    GsonConvert主要作用是将json转成实体对象。在那作用的呢?

    注意invoke方法中返回的是个OkHttpCall对象,所以每次拿这个call.enqueue()的时候,其实是okHttpCall.enqueue方法:

    @Override
    public void enqueue(final Callback<T> callback) {
        ...
        call = rawCall;//真正的okhttp包下的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
                    }
                }
    
                @Override
                public void onFailure(okhttp3.Call call, IOException e) {
                    callFailure(e);
                }
    
                private void callFailure(Throwable e) {
                    try {
                        callback.onFailure(OkHttpCall.this, e);
                    } catch (Throwable t) {
                        throwIfFatal(t);
                        t.printStackTrace(); // TODO this is not great
                    }
                }
            });
    }
    
    Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        ...
        //就是在这被调用的
        T body = responseConverter.convert(catchingBody);
    }
    

    相关文章

      网友评论

          本文标题:retrofit的CallAdapter和GsonConvert

          本文链接:https://www.haomeiwen.com/subject/fmwhrrtx.html