网络调度框架Retrofit2的使用与原理解析

 Retrofit是squareup公司的开源力作,和同属squareup公司开源的OkHttp,一个负责网络调度,一个负责网络执行,为Android开发者提供了即方便又高效的网络访问框架。Retrofit并不做网络请求,只是生成一个能做网络请求的对象,同时能够灵活的支持功能扩展,如自定义拦截器、网络请求适配器、数据转换适配器。

1. Retrofit实例构建过程分析

案例:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(HttpConst.HOST)
                .addConverterFactory(CustomGsonConverter.create(new GsonBuilder()
                        .disableHtmlEscaping()
                        .create()))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .client(buildOkHttp(builder))
                .build();

流程解析:

 使用建造者模式创建Retrofit对象,并配置与网络请求处理相关信息,主要包括;

(1) 指定HTTP请求Host URL;
(2) 指定网络请求适配器,比如RxJava2CallAdapter;
(3) 指定响应数据转换适配器,比如GsonConverter、PbConverter;
(4) 指定自定义网络请求客户端OkHttpClient;
(5) 指定处理响应的线程池;

注意:获取网络适配器和数据转换适配器使用了工厂模式适配器模式

Retrofit.Builder源码:

 public static final class Builder {
    // 平台信息,区分Android平台还是Java
    private final Platform platform;
    // 客户端OkHttpClient,继承于Call.Factory
    private @Nullable okhttp3.Call.Factory callFactory;
    // Http URL
    private @Nullable HttpUrl baseUrl;
    // 数据转换器列表
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    // 网络请求器列表
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    // 线程池
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
      this.platform = platform;
    }

    // Buidler构造方法
    // 在该方法中通过判断System.getProperty("java.vm.name")是否为"Dalvik"
    // 将this.platform = new Android();
    public Builder() {
      this(Platform.get());
    }
    
    ...
    
    public Retrofit build() {
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }
      // 1. 如果用户没有创建自定义的OkHttpClient
      // 就new一个出来
      // 注:OkHttpClient继承于接口Call.Factory
      // interface Factory {
      //    Call newCall(Request request);
      // }
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }
      // 2. 如果用户没有创建自定义的响应回调线程池
      // 就调用Android().defaultCallbackExecutor()获取MainThreadExecutor
      // 该方法继承于Executor,当执行execute(r)方法时,实际上使用主线程的Handler发送Message
      //      private final Handler handler = new Handler(Looper.getMainLooper());
      //
      //      @Override
      //      public void execute(Runnable r) {
      //        handler.post(r);
      //      }
      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }

      // Make a defensive copy of the adapters and add the default Call adapter.
      // 3. 将用户自定义网络请求适配器和默认的网络适配器添加到集合callAdapterFactories中
      // 其中,默认的网络适配器列表为DefaultCallAdapterFactory
      List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
      callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

      // Make a defensive copy of the converters.
      // 4. 将数据转换适配器器添加到集合中
      List<Converter.Factory> converterFactories =
          new ArrayList<>(
              1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

      // Add the built-in converter factory first. This prevents overriding its behavior but also
      // ensures correct behavior when using converters that consume all types.
      converterFactories.add(new BuiltInConverters());
      converterFactories.addAll(this.converterFactories);
      converterFactories.addAll(platform.defaultConverterFactories());
      // 5. 构建Retrofit对象
      return new Retrofit(
          callFactory,
          baseUrl,
          unmodifiableList(converterFactories),
          unmodifiableList(callAdapterFactories),
          callbackExecutor,
          validateEagerly);
    }
 }

注释1:设置默认网络请求适配器

 Android平台支持的默认网络请求适配器为DefaultCallAdapterFactory。

// Platform.defaultCallAdapterFactories()方法

List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
  @Nullable Executor callbackExecutor) {
DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
// 实例化一个DefaultCallAdapterFactory对象
// 作为Retrofit的默认网络请求适配器
return hasJava8Types
    ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
    : singletonList(executorFactory);
}

注释2:设置默认数据转换适配器

 Android平台没有默认数据转换适配器。

// Platform.defaultCallAdapterFactories()方法

List<? extends Converter.Factory> defaultConverterFactories() {
    return hasJava8Types ? singletonList(OptionalConverterFactory.INSTANCE) : emptyList();
}

2. Service接口实例创建过程分析

 这个接口并不是传统意义上的网络请求接口,这个接口不是用来获取数据的接口,而是用来生产对象的接口,这个接口相当于一个工厂,接口中每个函数的返回值不是网络数据,而是一个能进行网络请求的工作对象,我们要先调用函数获得工作对象,再用这个工作对象去请求网络数据。

案例:

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<GitHubRepos>> getRepos(@Path("user") String user);
    
    // Retrofit+RxJava
    @GET("users/{user}/repos")
    Observable<List<GitHubRepos>> getRepos(@Path("user") String user);
}

// 获取发起网络请求的Service实例对象
GitHubService service = retrofit.create(GitHubService.class);

流程解析:

 Retrofit使用注解声明网络请求 方法,包括指定HTTP请求方法请求头以及请求实体,然后再使用动态代理获取封装了网络请求方法的Service接口实例对象。Retrofit#create()源码如下:

public <T> T create(final Class<T> service) {
// 1. 检查Service接口的有效性
// 即Service必须是接口,且不能是static方法和default方法(后者需开启严格检查validateEagerly)
validateServiceInterface(service);

// 2. 动态代理模式
// 为service动态创建一个代理对象,并返回
// 当调用Service接口中的方法时,会触发invoke方法,该方法最终会通过反射调用对应的方法。
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 @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // If the method is a method from Object then defer to normal invocation.
            // 2-1 如果被调用的方法属于类的对象
            // 直接反射调用即可
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }

            // 2-2 如果被调用的方法是一个default方法,通过platform.invokeDefaultMethod完成调用
            // 否则,通过调用ServiceMethod的invoke方法完成最终的网络请求调用。其中,ServiceMethod通过loadServiceMethod获取
            // 注意:Service接口中的每一个method都对应一个ServiceMethod对象
            args = args != null ? args : emptyArgs;
            return platform.isDefaultMethod(method)
                ? platform.invokeDefaultMethod(method, service, proxy, args)
                : loadServiceMethod(method).invoke(args);
          }
        });
}

3. 发起网络请求与处理响应数据

 Retrofit本身用一个OkHttpCall的类负责处理网络请求,而我们在接口中定义需要定义很多种Call,例如Call,或者Flowable等,接口里的Call和Retrofit里的OkHttpCall并不一致,所以我们需要用一个CallAdapter去做一个适配转换。Retrofit底层虽然使用了OkHttpClient去处理网络请求,但她并没有使用okhttp3.call这个Call接口,而是自己又建了一个retrofit2.Call接口,OkHttpCall继承的是retrofit2.Call,与okhttp3.call只是引用关系。这样的设计符合依赖倒置原则,可以尽可能的与OkHttpClient解耦。

案例:

// 1. 使用默认网络适配器
// 异步请求
GitHubService service = retrofit.create(GitHubService.class);
Call<List<GitHubRepos> call = service.getRepos();
call.enqueue(new Callback<List<GitHubRepos>() {
    @Override
    public void onResponse(Call<List<GitHubRepos>> call, Response<List<GitHubRepos> response) {
       
    }

    @Override
    public void onFailure(Call<List<GitHubRepos>> call, Throwable throwable) {

    }
});

// 2. 使用RxJava2网络适配器
// 异步请求
GitHubService service = retrofit.create(GitHubService.class);
Observable<List<GitHubRepos> observable  = service.getRepos();
observable.subscribeOn(Schedulers.io())              
          .observeOn(AndroidSchedulers.mainThread())  // 主线程处理结果
          .subscribe(new Observer<List<GitHubRepos>>() {
            @Override
            public void onSubscribe(Disposable d) {
                ...// 初始化工作
              }
            
            @Override
            public void onNext(List<GitHubRepos> repos) {
                ...// 处理返回结果
            }

            @Override
            public void onComplete() {
                Log.d(TAG, "请求成功");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "请求失败");
            }

        });

 上述案例中,就是callAdapter做的事情就是把retrofit2.Call对象适配转换为Flowable对象

3.1 发起网络请求过程分析

(1)获取一个ServiceMethod对象;

 首先,从缓存获取method对应的ServiceMethod对象,如果不存在,则调用ServiceMethod.parseAnnotations()方法实例化一个对象,该方法会继续调用其子类HttpServiceMethod.parseAnnotations()方法。ServiceMethod源码如下:

/** 抽象类,ServiceMethod
 *  它将完成对Method注解解析,得到HTTP的各类请求参数
 *
 * 每个method对应的ServiceMethod,它的实现类为HttpServiceMethod
 *
 * @param <T>
 */
abstract class ServiceMethod<T> {
  /** 创建ServiceMethod
   *  完成对HTTP请求参数的解析
   * @param retrofit
   * @param method
   * @param <T>
   * @return
   */
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    // 1. 实例化一个RequestFactory
    // 该对象是对请求参数的封装
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }
    // 2. 实例化一个HttpServiceMethod对象,并返回
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  /** 执行mthod方法调用逻辑
   *
   *  实际调用的是HttpServiceMethod的invoke方法,它是ServiceMethod的唯一实现类
   *
   * @param args 参数
   * @return
   */
  abstract @Nullable T invoke(Object[] args);
}

ServiceMethod创建过程如下:

  • a. 反射解析method的注解信息,将请求参数封装到RequestFactory
  • b. 调用HttpServiceMethod.parseAnnotations方法创建ServiceMethod对象;

注释1RequestFactory.parseAnnotations()解析注解信息。

  
  final class RequestFactory {
    static RequestFactory parseAnnotations(Retrofit retrofit, Method method) {
      // 建造者模式,
      // 创建RequestFactory对象
      // 该对象是对HTTP请求相关参数的封装
      return new Builder(retrofit, method).build();
    }
  
    private final Method method;
    private final HttpUrl baseUrl;  // Http请求host
    final String httpMethod;        // Http请求方法,如POST、GET
    private final @Nullable String relativeUrl;
    private final @Nullable Headers headers; // Http请求头
    private final @Nullable MediaType contentType;
    private final boolean hasBody;   // Http请求是否有body
    private final boolean isFormEncoded; // Http请求是否为表单
    private final boolean isMultipart; // Http请求是否为Multipart
    private final ParameterHandler<?>[] parameterHandlers;
    final boolean isKotlinSuspendFunction;
 }

 请求参数注解,顾名思义,就是这些注解主要用于标注请求参数,当发起网络请求时,Retrofit的注解解析器会解析出被下列注解标注的请求参数,然后将这些数据拼接到请求URL填充到请求实体中,最终通过OkHttp请求网络数据。在这些注解中,@Field/@FieldMap/@Part/@PartMap/@Body主要用于POST请求中,@Path/@Query/@QueryMap主要用于GET请求中。请求参数注解列表如下:

请求参数注解作用
@Path用于Get请求时URL中的占位符
@Query用于Get请求传递请求参数
@QueryMap与@Query类似,用于传递不确定参数(即改成Map传参,key为各参数名)
@Field用于Post请求传递表单参数,需与@FormUrlEncoded配合使用
@FieldMap与@Field类似,用于传递不确定参数(即改成Map传参,key为各参数名)
@Part用于Post请求传递表单参数,适合上传文件,需配合@Multipart使用
@PartMap与@Part类似,适合上传多个文件,需配合@Multipart使用
@Body用于传递自定义数据给服务器,多用于post请求发送非表单数据
@Url用于指定请求路径,多用于Get请求时将路径当参数传入

注释2HttpServiceMethod.parseAnnotations()方法源码

abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    ...
    
    static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
  Retrofit retrofit, Method method, RequestFactory requestFactory) {
    // 1. 发射获取注解信息,和adapterType(即返回值类型)
    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    adapterType = method.getGenericReturnType();
    
    // 2. 创建网络请求适配器
    // 遍历所有支持的网络适配器对象,直到找到与返回类型adapterType一致的
    //    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;
    //      }
    //    }
    CallAdapter<ResponseT, ReturnT> callAdapter =
        createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
  }
  
    // 3. 创建数据转换适配器
    // 遍历所有支持的数据转换适配器,直到找到与响应类型responseType一致的
    //    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;
    //      }
    //    }
    Converter<ResponseBody, ResponseT> responseConverter =
        createResponseConverter(retrofit, method, responseType);
        
    // 4. 获取callFactory对象,它的类型就是OKHttpClient(可以由用户传入)
    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    
    // 5. 创建一个CallAdapted对象或SuspendForResponse对象
    // 需要判断请求方法是否为协程
    // 注:如果isKotlinSuspendFunction=true,说明请求方法是一个kotlin协程
    // 注:CallAdapted和SuspendForResponse均继承于HttpServiceMethod
    if (!isKotlinSuspendFunction) {
      return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForResponse<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
      return (HttpServiceMethod<ResponseT, ReturnT>)
          new SuspendForBody<>(
              requestFactory,
              callFactory,
              responseConverter,
              (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
              continuationBodyNullable);
    }
    
    protected abstract @Nullable ReturnT adapt(Call<ResponseT> call, Object[] args);
}

主要完成以下工作:

(1)根据adapterType,遍历匹配合适的网络适配器对象;
(2)根据responseType,遍历匹配合适的数据转换适配器对象responseConverter;
(3)获取callFactory对象,它的类型就是OKHttpClient;
(4)将创建好的requestFactory, callFactory, responseConverter, callAdapter创建一个CallAdapted(非协程)或SuspendForResponse对象(协程),它继承于HttpServiceMethod。

  • CallAdated类
  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) {
      // 1 返回网络适配器对象的Call给外界
      //调用具体网络请求适配器的adapt方法
      //最后返回一个Call对象(Default),或者Observable(RxJava)等
      //注意:参数call对象类型为OkHttpCall
      return callAdapter.adapt(call);
    }
  }

(2)网络请求过程

 当访问某个网络方法时,ServiceMethod#invoke()方法将被调用,该方法是一个抽象方法,实际调用的是它的实现类HttpServiceMethod#invoke()方法。

a. ServiceMethod#invoke()

abstract class ServiceMethod<T> {
    ...
    
    /** 1. 执行mthod方法调用逻辑
   *
   *  实际调用的是HttpServiceMethod的invoke方法,它是ServiceMethod的唯一实现类
   *
   * @param args 参数
   * @return
   */
  abstract @Nullable T invoke(Object[] args);
}

b. HttpServiceMethod#invoke()

  • 首先,实例化一个OkHttpCall对象,它是对OkHttp的Call的封装;
  • 其次,调用具体的网络请求适配器,返回Call或者Observable给外界;
abstract class HttpServiceMethod<ResponseT, ReturnT> extends ServiceMethod<ReturnT> {
    ...
    
  /** 执行真实的请求方法调用逻辑
   *
   * @param args
   * @return 响应结果,是一个Call或Observable或Maybe...
   */
  @Override
  final @Nullable ReturnT invoke(Object[] args) {
    // 1. 实例化一个OkHttpCall对象,它继承于retrofit自定义的Call接口
    // 它是对OkHttp的Call的封装,在这里面会对响应进行数据转换
    // 然后根据这个call对象,调用HttpServiceMethod的adapter方法
    // 该方法是一个抽象方法,最终实现在CallAdapted或SuspendForBody或SuspendForResponse类中(继承于HttpServiceMethod)
    Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    
    // 2.返回一个Call对象(Default),或者Observable(RxJava)等给外界
    // 它是HttpServiceMethod的抽象方法,最终由其子类CallAdapted(非协程)实现
    return adapt(call, args);
  }
}

c. CallAdapted#adapt():调用具体的网络请求适配器,生成Call或者Observable等给外界。

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);
      // 1. 设置具体的网络请求适配器
      // 默认为DefaultCallAdapterFactory
      // RxJava2为RxJava2CallAdapter
      this.callAdapter = callAdapter;
    }
    
    @Override
    protected ReturnT adapt(Call<ResponseT> call, Object[] args) {
      // 2. 返回网络适配器对象的Call给外界
      //调用具体网络请求适配器的adapt方法
      //最后返回一个Call对象(Default),或者Observable(RxJava)等
      //注意:参数call对象类型为OkHttpCall
      return callAdapter.adapt(call);
    }
}

d. 网络适配器发起网络请求

 最终的网络请求将由具体的网络适配器callAdapter实现,它是之前在创建ServiceMethod对象时被指定,具体的网络适配器就包括DefaultCallAdapterFactory或RxJava2CallAdapter等,它们的adapt()方法将返回与其关联的网络请求对象(如CallObservable)给外界发起网络请求。

  • DefaultCallAdapterFactory#adapt():默认网络请求适配器,返回一个Call
/**
 * 默认网络请求适配器
 */
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  // 线程池
  //    用于处理响应回调,由构造方法传入,默认为MainThreadExecutor
  private final @Nullable Executor callbackExecutor;

  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  /** 根据响应返回类型(returnType),返回对应的适配器对象
   *
   * @param returnType 响应返回类型,转换后必须为Call.class
   * @param annotations 注解信息
   * @param retrofit Retrofit对象
   * @return
   */
  @Override
  public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    // 1. 响应类型必须为Call
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    if (!(returnType instanceof ParameterizedType)) {
      throw new IllegalArgumentException(
          "Call return type must be parameterized as Call<Foo> or Call<? extends Foo>");
    }
    final Type responseType = Utils.getParameterUpperBound(0, (ParameterizedType) returnType);

    // 2. 设置响应回调处理线程池
    // 如果传入的annotations列表中包含SkipCallbackExecutor.class
    // 则将executor = null
    final Executor executor =
        Utils.isAnnotationPresent(annotations, SkipCallbackExecutor.class)
            ? null
            : callbackExecutor;
    // 3. 创建CallAdapter对象
    // 最终将通过该对象的adapt方法返回适配器对象,规则为
    // 如果executor=null,则返回用户传入的Call对象
    // 否则,返回new ExecutorCallbackCall(),该类继承于Call
    return new CallAdapter<Object, Call<?>>() {
      @Override
      public Type responseType() {
        return responseType;
      }

      @Override
      public Call<Object> adapt(Call<Object> call) {
        // ExecutorCallbackCall使用了代理模式(均继承于interface Call<T>)
        // ExecutorCallbackCall就是call的代理对象,它持有了call对象的引用
        // 注意:参数call的类型为OkHttpCall
        return executor == null ? call : new ExecutorCallbackCall<>(executor, call);
      }
    };
  }

  static final class ExecutorCallbackCall<T> implements Call<T> {
    final Executor callbackExecutor;
    // 真实的Call对象
    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");
      // 1 发起异步网络请求,这里只是处理响应结果返回给外界
      // delegate类型为OkHttpCall,因此调用的是OkHttpCall.enqueue方法,它将真正调用OkHttp的Call
      // 当响应结果返回后response,通过响应回调线程池(默认为MainThreadExecutor)
      // MainThreadExecutor最终将结果由子线程自动切换到主线程
      delegate.enqueue(
          new Callback<T>() {
            // response是已经做了数据格式转换
            @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));
            }
          });
    }

    @Override
    public boolean isExecuted() {
      return delegate.isExecuted();
    }

    // 同步请求
    @Override
    public Response<T> execute() throws IOException {
      return delegate.execute();
    }

    @Override
    public void cancel() {
      delegate.cancel();
    }

    @Override
    public boolean isCanceled() {
      return delegate.isCanceled();
    }

    @SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
    @Override
    public Call<T> clone() {
      return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
    }

    @Override
    public Request request() {
      return delegate.request();
    }

    @Override
    public Timeout timeout() {
      return delegate.timeout();
    }
  }
}

  • RxJava2CallAdapter:RxJava网络请求适配器,返回一个Observable
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;
  }

  @Override
  public Object adapt(Call<R> call) {
    // 1 根据异步标志isAsync
    // 决定创建异步Observable-->CallEnqueueObservable
    // 同步Observable--->CallExecuteObservable
    Observable<Response<R>> responseObservable =
        isAsync ? new CallEnqueueObservable<>(call) : new CallExecuteObservable<>(call);
    // 2 创建Observable
    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }
    // 3 指定被观察者执行线程
    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }
    // 4 根据响应的返回类型
    // 将Observable转换为对应的对象,如Single、Maybe等
    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);
  }
}

3.2 数据转换过程分析

a. OkHttpCall#enqueue():默认网络适配器,异步请求

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;
  
   /** 完成最终的网络请求,并处理响应结果转换
   *
   * @param callback 回调接口,外界在该接口方法中做返回数据封装
   */
  @Override
  public void enqueue(final Callback<T> callback) {
    Objects.requireNonNull(callback, "callback == null");

    // a. 实例化一个OkHttp的Call对象
    // 在发起网络请求准确之前,会做状态校验,并调用响应的回调接口
    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      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();    // 取消
    }

    // b. 真正的发起异步网络请求
    // 并调用parseResponse()使用用户指定的数据格式,对响应结果做数据格式转换
    call.enqueue(
        new okhttp3.Callback() {
          @Override
          public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
              // b-1 使用数据转换适配器对象对响应结果做数据格式转换
              response = parseResponse(rawResponse);
            } catch (Throwable e) {
              throwIfFatal(e);
              callFailure(e);
              return;
            }
            // b-2 将最终的响应结果回调出去
            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) {
            // b-3 网络请求失败回调
            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 {
    // b-1-1 获取响应实体body
    // 并重新创建一个不包含响应实体的ResponseBody对象,以便后续使用
    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) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    // b-1-2 使用数据转换适配器转换数据
    // 比如GsonResponseBodyConverter,就是将json格式数据转换为对应的实体对象
    // 比如ProtoResponseBodyConverter,就是将json格式数据转换为对应的PB对象
    // 注:GSON、PB的请求参数也需要转换,它们分别对应的是
    // 比如GsonRequestBodyConverter\ProtoRequestBodyConverter
    try {
      T body = responseConverter.convert(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

}

b. RxJava网络适配器处理响应

  • CallExecuteObservable#subscribeActual():同步操作
/** 发起同步网络请求,将响应结果通过RxJava发射出去
 *
 * @param <T>
 */
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.
    // 1 拷贝Call,便于每个Observer对应一个单独Call
    Call<T> call = originalCall.clone();
    // 2 设置Observer的Dispose
    CallDisposable disposable = new CallDisposable(call);
    observer.onSubscribe(disposable);
    if (disposable.isDisposed()) {
      return;
    }

    // 3 发起同步网络请求,并将结果通过observer.onNext发射出去
    // 需要注意的是observable.subscribeOn
    // 指定为子线程操作,因为是网络请求
    boolean terminated = false;
    try {
      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;
      // 当用户调用Dispose.dispose()方法时
      // 取消网络请求
      call.cancel();
    }

    @Override
    public boolean isDisposed() {
      return disposed;
    }
  }
}
  • CallEnqueueObservable#subscribeActual():异步操作

/** 发起异步网络请求,将响应转换为RxJava发射出去
 *
 * @param <T>
 */
final class CallEnqueueObservable<T> extends Observable<Response<T>> {
  private final Call<T> originalCall;

  CallEnqueueObservable(Call<T> originalCall) {
    this.originalCall = originalCall;
  }

  // Obervable执行时,该方法会被触发
  @Override
  protected void subscribeActual(Observer<? super Response<T>> observer) {
    // 1.拷贝Call,便于每个Observer对应一个单独Call
    Call<T> call = originalCall.clone();
    // 2.实例化一个CallCallback对象,继承于Disposable和Callback
    // 该对象完成将响应结果转换成RxJava的回调(代理模式CallCallback代理originalCall)
    CallCallback<T> callback = new CallCallback<>(call, observer);
    // 3.调用observer的onSubscribe
    // 这个callback实际上是一个Disposable,便于调用者终止网络请求
    observer.onSubscribe(callback);
    // 4 执行异步网络请求
    // 最终还是调用Call.enqueue方法
    if (!callback.isDisposed()) {
      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的代理
     *
     * @param call 原始Call
     * @param observer Observer对象
     */
    CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
      this.call = call;
      this.observer = observer;
    }

    /** 网络响应结果回调方法
     *
     * @param call 发起网络请求的Call对象
     * @param response 响应结果
     */
    @Override
    public void onResponse(Call<T> call, Response<T> response) {
      // (1)"水管"被切断,终止向外发射数据
      if (disposed) return;

      try {
        //(2)调用Observer的onNext方法
        // 将响应结果response发射出去
        observer.onNext(response);

        //(3)调用Observer的onComplete方法
        // 结束数据发射
        if (!disposed) {
          terminated = true;
          observer.onComplete();
        }
      } catch (Throwable t) {
        Exceptions.throwIfFatal(t);
        if (terminated) {
          RxJavaPlugins.onError(t);
        } else if (!disposed) {
          try {
            // (4)调用Observer的onError方法
            // 向外发射异常
            observer.onError(t);
          } catch (Throwable inner) {
            Exceptions.throwIfFatal(inner);
            RxJavaPlugins.onError(new CompositeException(t, inner));
          }
        }
      }
    }

    @Override
    public void onFailure(Call<T> call, Throwable t) {
      if (call.isCanceled()) return;

      try {
        // (4)调用Observer的onError方法
        // 向外发射异常
        observer.onError(t);
      } catch (Throwable inner) {
        Exceptions.throwIfFatal(inner);
        RxJavaPlugins.onError(new CompositeException(t, inner));
      }
    }

    @Override
    public void dispose() {
      disposed = true;
      // 当用户调用Dispose.dispose()方法时
      // 取消网络请求
      call.cancel();
    }

    @Override
    public boolean isDisposed() {
      return disposed;
    }
  }
}

 Retrofit实现原理总结:Retrofit是一个网络调度框架,它并不做网络请求,只是生成一个能做网络请求的对象。具体过程为Retrofit使用动态代理去定制接口定义的Call网络工作对象,用适配器去把底层的Call对象转换为目标Call对象,用函数解析/OkHttpClient/数据转换等实现对Call对象的适配转换,并能处理真正的网络请求。

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:白松林 返回首页