阅读 1366

Retrofit2.6.2源码解析

OkHttp4.2.2源码解析

Retrofit2.6.2源码解析


前一篇对OkHttp4.2.2源码进行了简单解析,并附上了相应的流程图。直接使用OkHttp还不够方便,所以又诞生了Retrofit。截止本文编写日期,Retrofit最新版为2.6.2,其自身使用OkHttp3.14.4、coroutines1.3.2。虽然Retrofit使用的不是最新版的OkHttp,但也不影响之前分析的流程。

一、流程图

流程图

二、简单使用

  1. 添加依赖
implementation("com.squareup.retrofit2:retrofit:2.6.2")
复制代码
  1. 定义请求接口
interface ApiService {
    @GET("users/{user}/repos")
    suspend fun listRepos(
            @Path("user") user: String
    ): FoodResponse<List<Repo>>
}
复制代码
  1. 构建Retrofit生成Api实例
val baseUrl = "https://api.github.com/"

val okClient = OkHttpClient.Builder()
    .addInterceptor(loggingInterceptor)
    ......
    .build()

Retrofit.Builder()
    .baseUrl(baseUrl)
    .client(okClient) //有默认,非必须
    .addConverterFactory(GsonConverterFactory.create())
    .build()
    
val service = retrofit.create(ApiService::class.java)
复制代码
  1. 发起请求
//1. 回调方式
service.listRepos1("zx").enqueue(object : Callback<List<Repo>> {
    override fun onFailure(call: Call<List<Repo>>, t: Throwable) {

    }

    override fun onResponse(call: Call<List<Repo>>, response: Response<List<Repo>>) {
    }
})
    
//2. 协程方式
val repos = service.listRepos("zx")

//3. RxJava等
})
复制代码

三、源码解析

通过上面4步,演示了如何通过Retrofit发起一次网络请求,接下来就根据上面的流程看看源码,点到即止。

构建Retrofit

在构建Retrofit这步我们主要关注3个,分别是 Builder方法、 baseUrl()方法和 build()方法

  1. Builder
public Builder() {
    // 平台获取,Platform我们在OkHttp分析中也见到过
    this(Platform.get());
}
复制代码
  1. baseUrl
public Builder baseUrl(String baseUrl) {
    Objects.requireNonNull(baseUrl, "baseUrl == null");
    return baseUrl(HttpUrl.get(baseUrl));
}

public Builder baseUrl(HttpUrl baseUrl) {
    Objects.requireNonNull(baseUrl, "baseUrl == null");
    List<String> pathSegments = baseUrl.pathSegments();
    // 检查baseUrl是否以/结尾,不是就抛出异常
    if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
        throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
    }
    this.baseUrl = baseUrl;
    return this;
}
复制代码

baseUrl的作用就不说了,这里我们看下注释那行,baseUrl不以 / 结尾,就会抛出异常。

需要注意的是这里的baseUrl类型是HttpUrl类型,所以跟我们使用设置的String是不一样的。HttpUrl.get对我们设置进行了处理,所以我们的String类型baseUrl不以 / 结尾不一定会得到异常。

  1. build
public Retrofit build() {
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
    }

    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
        //如果没有设置callFactory,则默认使用OkHttpClient,也就是我们常说得Retrofit默认使用OkHttp
        //OkHttpClient实现了okhttp3.Call.Factory接口
        callFactory = new OkHttpClient();
    }

    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
        //callbackExecutor
        //如果没有设置回调执行者,则使用平台默认回调执行者
        callbackExecutor = platform.defaultCallbackExecutor();
    }

    // Make a defensive copy of the adapters and add the default Call adapter.
    // 网络请求适配工厂集合 = 使用者设置适配工厂 + 平台默认适配工厂
    // 使用者设置适配工厂
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    // 平台默认适配工厂,注意这里传入了回调执行者
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

    // Make a defensive copy of the converters.
    // 数据转换工厂集合 = 内置转换工厂 + 使用者设置转换工厂 + 平台默认转换工厂
    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());

    // 构建 Retrofit
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
            unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
复制代码

build方法主要是参数的处理(对null值和平台默认值的处理)并构建出Retrofit实例。

上面多次出现Platform字眼,接下来看看这个类里做了什么?

class Platform {
    private static final Platform PLATFORM = findPlatform();

    static Platform get() {
        return PLATFORM;
    }

    // 查找平台
    private static Platform findPlatform() {
        try {
            Class.forName("android.os.Build");
            if (Build.VERSION.SDK_INT != 0) {
                return new Android();
            }
        } catch (ClassNotFoundException ignored) {
        }
        try {
            Class.forName("java.util.Optional");
            return new Java8();
        } catch (ClassNotFoundException ignored) {
        }
        return new Platform();
    }

    ......

    @IgnoreJRERequirement // Only classloaded and used on Java 8.
    static class Java8 extends Platform {
    ......
    }

    static class Android extends Platform {
        @IgnoreJRERequirement // Guarded by API check.
        @Override
        boolean isDefaultMethod(Method method) {
            if (Build.VERSION.SDK_INT < 24) {
                return false;
            }
            return method.isDefault();
        }

        @Override
        public Executor defaultCallbackExecutor() {
            // 返回默认回调执行者
            return new MainThreadExecutor();
        }

        @Override
        List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
                @Nullable Executor callbackExecutor) {
            if (callbackExecutor == null) throw new AssertionError();
            //构建默认适配工厂,注意这里传入回调执行者
            DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
            //返回默认的适配工厂
            return Build.VERSION.SDK_INT >= 24
                    ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
                    : singletonList(executorFactory);
        }

        @Override
        int defaultCallAdapterFactoriesSize() {
            return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
        }

        @Override
        List<? extends Converter.Factory> defaultConverterFactories() {
            //返回默认的转换工厂
            return Build.VERSION.SDK_INT >= 24
                    ? singletonList(OptionalConverterFactory.INSTANCE)
                    : Collections.<Converter.Factory>emptyList();
        }

        @Override
        int defaultConverterFactoriesSize() {
            return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
        }

        // Android 主线程执行者
        static class MainThreadExecutor implements Executor {
            private final Handler handler = new Handler(Looper.getMainLooper());

            @Override
            public void execute(Runnable r) {
                handler.post(r);
            }
        }
    }
}
复制代码

总结3点:

  • 通过findPlatform方法可以看出2.6.2支持Android和Java。(记得2.0.1的时候还有iOS字样,另外GitHub最新代码把Java8也移除了。)
  • 设置了平台默认回调执行者(Handler 主线程)、默认适配工厂和默认转换工厂
  • Java8 和 Android 24是一个分界点(具体可以看CompletableFutureCallAdapterFactory和OptionalConverterFactory)

创建Api实例

上面分析了Retrofit的构建过程,紧接着看看创建Api实例部分。实际创建Api实例似乎很简单,只需要如下一行代码:

val service = retrofit.create(ApiService::class.java)
复制代码

难道真这么简单么?接着往下看:

public <T> T create(final Class<T> service) {
    // 校验 Service Interface 是否满足要求
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
        // 是否需要提前验证Service Interface方法,
        // true:在调用create时就把相应方法进行处理加入到serviceMethodCache缓存起来
        // false:在调用执行InvocationHandler.invoke时再做处理和缓存
        // true 和 false最终都是调用loadServiceMethod
        eagerlyValidateMethods(service);
    }
    // 使用动态代理拿到请求接口所有注解配置,创建网络请求接口实例
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
            new InvocationHandler() {
                ......
            });
}

// 提前验证Service Interface方法
private void eagerlyValidateMethods(Class<?> service) {
    Platform platform = Platform.get();
    for (Method method : service.getDeclaredMethods()) {
        if (!platform.isDefaultMethod(method) && !Modifier.isStatic (method.getModifiers())) {
            // isDefaultMethod 是否平台默认方法,2.6.2返回的fasle
            // isStatic 是否被static修饰
            loadServiceMethod(method);
        }
    }
}

复制代码

果然,这样看很简单呐。这一步先不针对loadServiceMethod及其后续操作进一步分析,放在发起请求invoke执行时再看,因为平时我也没有设置过validateEagerly。

发起网络请求

public <T> T create(final Class<T> service) {
    ......
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
            new InvocationHandler() {
                private final Platform platform = Platform.get();
                private final Object[] emptyArgs = new Object[0];

                // 执行newProxyInstance出来实例中的方法
                @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.
                    // Object默认方法
                    if (method.getDeclaringClass() == Object.class) {
                        return method.invoke(this, args);
                    }
                    // 平台默认方法
                    if (platform.isDefaultMethod(method)) {
                        return platform.invokeDefaultMethod(method, service, proxy, args);
                    }
                    // 加载Service Interface方法,调用invoke创建OkHttpCall发起请求
                    return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
                }
            });
}

// ConcurrentHashMap支持多线程访问并且线程安全
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

ServiceMethod<?> loadServiceMethod(Method method) {
    // 获取缓存
    ServiceMethod<?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
        result = serviceMethodCache.get(method);
        if (result == null) {
            // 解析注解,生成ServiceMethod
            result = ServiceMethod.parseAnnotations(this, method);
            // serviceMethodCache 加入缓存
            serviceMethodCache.put(method, result);
        }
    }
    return result;
}

复制代码

跟进ServiceMethod.parseAnnotations

abstract class ServiceMethod<T> {
    static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
        // 解析注解参数
        // 主要解析请求类型 baseUrl relativeUrl 以及方法注解 参数类型 参数注解等等
        RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

        ......

        // HttpServiceMethod是跟进ServiceMethod子类
        // 在parseAnnotations中创建了callAdapter和responseConverter
        return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
    }

    // 创建OkHttpCall,通过adapt发起请求
    abstract @Nullable
    T invoke(Object[] args);
}

复制代码

再跟进HttpServiceMethod.parseAnnotations看看

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(
        Retrofit retrofit, Method method, RequestFactory requestFactory) {
    boolean isKotlinSuspendFunction = requestFactory.isKotlinSuspendFunction;
    boolean continuationWantsResponse = false;
    boolean continuationBodyNullable = false;

    Annotation[] annotations = method.getAnnotations();
    Type adapterType;
    if (isKotlinSuspendFunction) {
        // 是 Kotlin Suspend 方法
        Type[] parameterTypes = method.getGenericParameterTypes();
        Type responseType = Utils.getParameterLowerBound(0,
                (ParameterizedType) parameterTypes[parameterTypes.length - 1]);
        if (getRawType(responseType) == Response.class && responseType instanceof ParameterizedType) {
            // Unwrap the actual body type from Response<T>.
            responseType = Utils.getParameterUpperBound(0, (ParameterizedType) responseType);
            // 返回结果被Response包含 如:Response<T>
            continuationWantsResponse = true;
        } else {
            // TODO figure out if type is nullable or not
            // Metadata metadata = method.getDeclaringClass().getAnnotation(Metadata.class)
            // Find the entry for method
            // Determine if return type is nullable or not
        }

        adapterType = new Utils.ParameterizedTypeImpl(null, Call.class, responseType);
        // 跳过回调执行者注解
        annotations = SkipCallbackExecutorImpl.ensurePresent(annotations);
    } else {
        adapterType = method.getGenericReturnType();
    }
    
    // 根据retrofit, method, adapterType, annotations 创建CallAdapter
    CallAdapter<ResponseT, ReturnT> callAdapter =
            createCallAdapter(retrofit, method, adapterType, annotations);
    Type responseType = callAdapter.responseType();
    if (responseType == okhttp3.Response.class) {
        throw methodError(method, "'"
                + getRawType(responseType).getName()
                + "' is not a valid response body type. Did you mean ResponseBody?");
    }
    if (responseType == Response.class) {
        throw methodError(method, "Response must include generic type (e.g., Response<String>)");
    }
    // TODO support Unit for Kotlin?
    if (requestFactory.httpMethod.equals("HEAD") && !Void.class.equals(responseType)) {
        throw methodError(method, "HEAD method must use Void as response type.");
    }

    // 根据retrofit, method, adapterType 创建Converter
    Converter<ResponseBody, ResponseT> responseConverter =
            createResponseConverter(retrofit, method, responseType);

    okhttp3.Call.Factory callFactory = retrofit.callFactory;
    if (!isKotlinSuspendFunction) {
        // 非Kotlin Suspend方法
        return new CallAdapted<>(requestFactory, callFactory, responseConverter, callAdapter);
    } else if (continuationWantsResponse) {
        //Kotlin Suspend方法且被Response包含
        //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
        return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForResponse<>(requestFactory,
                callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter);
    } else {
        //Kotlin Suspend方法且未被Response包含
        //noinspection unchecked Kotlin compiler guarantees ReturnT to be Object.
        return (HttpServiceMethod<ResponseT, ReturnT>) new SuspendForBody<>(requestFactory,
                callFactory, responseConverter, (CallAdapter<ResponseT, Call<ResponseT>>) callAdapter,
                continuationBodyNullable);
    }
}
复制代码

HttpServiceMethod.parseAnnotations最后返回了HttpServiceMethod,回到Retrofit.create方法执行invokede 调用。HttpServiceMethod中具体实现了invoke如下:

@Override final @Nullable ReturnT invoke(Object[] args) {
//创建Call对象
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
    // adapt 也是个抽象方法,具体实现在CallAdapted,SuspendForResponse,SuspendForBody
    return adapt(call, args);
}
复制代码

上面还有比较重要的2点 createCallAdapter、createResponseConverter 方法,这里看看CallAdapter的创建。通过createCallAdapter -> retrofit.callAdapter -> nextCallAdapter:

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
                                         Annotation[] annotations) {
    ......

    int start = callAdapterFactories.indexOf(skipPast) + 1;
    // 遍历 Retrofit.build 构建的 callAdapterFactories 集合,寻找合适的适配工厂
    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(builder.toString());
}
复制代码

怎么来找对应的callAdapter,其实很简单,根据特定类型就可以了(比如如果返回Call 就是默认的,被suspend修饰就是协程,可以看看CallAdapterFactory的get方法)。

接下来看看实现了HttpServiceMethod的SuspendForBody是怎么实现的:

  static final class SuspendForBody<ResponseT> extends HttpServiceMethod<ResponseT, Object> {
    private final CallAdapter<ResponseT, Call<ResponseT>> callAdapter;
    private final boolean isNullable;

    ......

    @Override protected Object adapt(Call<ResponseT> call, Object[] args) {
      call = callAdapter.adapt(call);

      //noinspection unchecked Checked by reflection inside RequestFactory.
      Continuation<ResponseT> continuation = (Continuation<ResponseT>) args[args.length - 1];

      /**
      像在await和awaitNullable内部一样,
      对OkHttp Call.enqueue()的调用有时可以在异常返回之前调用提供的回调,
      而调用栈帧可以返回。 协程将拦截Continuation的后续调用,并同步引发异常。
      如果未在接口方法中声明检查的异常,则Java代理无法引发检查的异常。 
      为了避免将同步检查的异常包装在UndeclaredThrowableException中,
      将其拦截并提供给帮助程序,该帮助程序将强制执行挂起操作,
      以便可以将其传递给继续操作以绕过此限制。
      **/
      try {
        // 调用具体的扩赞方法
        return isNullable
            ? KotlinExtensions.awaitNullable(call, continuation)
            : KotlinExtensions.await(call, continuation);
      } catch (Exception e) {
        return KotlinExtensions.yieldAndThrow(e, continuation);
      }
    }
  }
复制代码

接下来是扩展方法await实现如下:

suspend fun <T : Any> Call<T>.await(): T {
  return suspendCancellableCoroutine { continuation ->
    continuation.invokeOnCancellation {
      cancel()
    }
    // 实际就是调用call.enqueue
    enqueue(object : Callback<T> {
      override fun onResponse(call: Call<T>, response: Response<T>) {
        if (response.isSuccessful) {
          val body = response.body()
          if (body == null) {
            val invocation = call.request().tag(Invocation::class.java)!!
            val method = invocation.method()
            val e = KotlinNullPointerException("Response from " +
                method.declaringClass.name +
                '.' +
                method.name +
                " was null but response body type was declared as non-null")
            continuation.resumeWithException(e)
          } else {
            //携带数据切回挂起处,等同于callback
            continuation.resume(body)
          }
        } else {
          continuation.resumeWithException(HttpException(response))
        }
      }

      override fun onFailure(call: Call<T>, t: Throwable) {
        continuation.resumeWithException(t)
      }
    })
  }
}
复制代码

当执行到KotlinExtensions.await/awaitNullable时,就会执行相应扩展函数挂起。不难发现最终还是通过Call.enqueue发起请求,得到相应结果则通过相应的resume函数恢复挂起。这个Call对象即是上面invoke中的OkHttpCall,而它的创建方式如下。不难猜测最终发起请求和数据转换都在它里面,所以上面的await扩展中调用的enqueue方法也在其中实现。

//避免回滚上去看OkHttpCall,所以在这儿由cv了一次
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
复制代码

看看OkHttpCall的enqueue方法

@Override public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    ......
    
    //经过一些列判断操作 最终发起请求
    call.enqueue(new okhttp3.Callback() {
        @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
            Response<T> response;
            try {
                // 解析Response
                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
            }
        }

        ......
    });
}

// 解析响应数据
Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    ......

    ExceptionCatchingResponseBody catchingBody = new ExceptionCatchingResponseBody(rawBody);
    try {
        //responseConverter 最终通过Converter解析完毕数据
        T body = responseConverter.convert(catchingBody);
        return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
        ......
    }
    
复制代码

四、总结

Retrofit通过接口注解简化网络请求配置,采用动态代理加载解析注解执行方法。然后通过OkHttpCall发起请求,获得响应后通过Converter进行数据转换后交给CallAdapter把最终数据交给开发者。

通过对Retrofit的使用和源码了解,Retrofit确实是封装了OkHttp,并且大量使用注解和设计模式,比如建造者模式、动态代理模式、工厂模式、适配器模式等等。

虽然这是基于2.6.2解析,但是看最新提交已有些许改版,前面也提到一点儿。

五、补充

线程切换

因为上面是用的协程,所以没有看到是如何进行线程切换的,现在我们来see 1 see,注释都加了。如下:

final class DefaultCallAdapterFactory extends CallAdapter.Factory {
  private final @Nullable Executor callbackExecutor;

  // 传入参数为回调执行者,还记得在哪儿传入的么?
  // Retrofit的build方法,根据相关平台里面来的
  DefaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
    this.callbackExecutor = callbackExecutor;
  }

  // 此方法用于createCallAdapter
  @Override public @Nullable CallAdapter<?, ?> get(
      Type returnType, Annotation[] annotations, Retrofit retrofit) {
    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);

    //获取执行者(协程不需要)
    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) {
        // 返回call,非协程方式用ExecutorCallbackCall包一层
        return executor == null
            ? call
            : new ExecutorCallbackCall<>(executor, 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) {
      checkNotNull(callback, "callback == null");
    
      // 此处的delegate就是OkHttpCall
      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(Call<T> call, final Response<T> response) {
          //回调执行者完成线程切换
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                // 通过callback回调了结果
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

        @Override public void onFailure(Call<T> call, final Throwable t) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              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();
    }
  }
}
复制代码
关注下面的标签,发现更多相似文章
评论