Retrofit核心源码分析(三)- Call逻辑分析和扩展机制

在前面的两篇文章中,我们已经对 Retrofit 的注解解析、动态代理、网络请求和响应处理机制有了一定的了解。在这篇文章中,我们将深入分析 Retrofit 的 Call 逻辑,并介绍 Retrofit 的扩展机制。

一、Call 逻辑分析

Call 是 Retrofit 中最基本的操作单元,它代表一个 HTTP 请求。在 Retrofit 中,我们通过接口定义请求的方式,并通过动态代理生成接口的实现类。这个实现类中的方法都会返回一个 Call 对象,通过这个对象我们可以发起网络请求,并获得响应结果。

Retrofit 的 Call 逻辑可以用以下代码来描述:

public interface Call<T> {
    Response<T> execute() throws IOException;
    void enqueue(Callback<T> callback);
    void cancel();
    boolean isExecuted();
    boolean isCanceled();
    Call<T> clone();
}

在这个接口中,我们可以看到 Retrofit 定义了五个方法,分别是 executeenqueuecancelisExecutedisCanceled。我们来逐一分析这些方法的作用。

execute 方法

execute方法用于同步发起 HTTP 请求,当我们调用execute()方法时,它会立即发起网络请求,并且阻塞当前线程直到请求结束,最后返回一个响应对象Response。这种方式适用于简单的网络请求,但不适合于在主线程中执行请求,因为会阻塞 UI 线程。

以下是execute()方法的部分代码:

@Override
public Response<T> execute() throws IOException {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already executed.");
    executed = true;
  }
  captureCallStackTrace();
  try {
    client.dispatcher().executed(this);
    Response<T> result = getResponseWithInterceptorChain();
    if (result == null) throw new IOException("Canceled");
    return result;
  } catch (IOException e) {
    throw timeoutExit(e);
  } finally {
    client.dispatcher().finished(this);
  }
}

上述代码中,我们可以看到该方法首先会检查当前请求是否已经执行过,如果已经执行过则会抛出一个异常。然后会将该请求加入到Dispatcher中的执行队列中。接下来会调用getResponseWithInterceptorChain()方法来获取响应结果。如果结果为null,则表示请求已经被取消,否则返回响应结果。最后,会将该请求从执行队列中移除。

enqueue 方法

enqueue方法用于异步发起 HTTP 请求,它会在后台线程中发起网络请求,并在请求结束后将结果返回到主线程中。因此,enqueue()方法适用于在主线程中执行网络请求。

以下是enqueue()方法的部分代码:

@Override
public void enqueue(Callback<T> callback) {
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already executed.");
    executed = true;
  }
  captureCallStackTrace();
  client.dispatcher().enqueue(new AsyncCall(callback));
}

上述代码中,我们可以看到该方法首先会检查当前请求是否已经执行过,如果已经执行过则会抛出一个异常。然后会将该请求封装成一个AsyncCall对象,加入到Dispatcher中的异步队列中。

AsyncCall继承自RealCall,它实现了Runnable接口,表示可以在后台线程中执行。在AsyncCall中,我们可以看到它会在后台线程中执行网络请求,并将结果通过Callback回调返回到主线程中。

final class AsyncCall extends RealCall.AsyncCall {
  private final Callback<T> responseCallback;

  AsyncCall(Callback<T> responseCallback) {
    super();
    this.responseCallback = responseCallback;
  }

  @Override protected void execute() {
    boolean signalledCallback = false;
    try {
      Response<T> response = getResponseWithInterceptorChain();
      if (retryAndFollowUpInterceptor.isCanceled()) {
        signalledCallback = true;
        responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
      } else {
        signalledCallback = true;
        responseCallback.onResponse(RealCall.this, response);
      }
    } catch (IOException e) {
      if (signalledCallback) {
        // Do not signal the callback twice!
        Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
      } else {
        responseCallback.onFailure(RealCall.this, e);
      }
    } finally {
      client.dispatcher().finished(this);
    }
  }

  @Override public String toString() {
    return RealCall.this.toString();
  }
}

AsyncCall中,首先会调用getResponseWithInterceptorChain()方法来获取响应结果。如果请求被取消,则会调用onFailure()方法将结果返回到主线程中。否则,会调用onResponse()方法将结果返回到主线程中。无论请求成功或失败,都会调用finished()方法将该请求从异步队列中移除。

cancel 方法

cancel方法用于取消正在执行的请求。如果请求已经完成或已经取消,则该方法不会有任何效果。

isExecuted 方法

isExecuted方法用于判断请求是否已经执行。如果已经执行,则返回true,否则返回false。

isCanceled 方法

isCanceled方法用于判断请求是否已经取消。如果已经取消,则返回true,否则返回false。

clone 方法

clone方法用于创建一个当前 Call 对象的副本。这个方法一般用于发起多次相同的请求。

以上这些方法就构成了 Retrofit 的 Call 逻辑。在使用 Retrofit 时,我们一般会通过executeenqueue方法发起 HTTP 请求,并通过传入的Callback对象来处理响应结果。

二、扩展机制

Retrofit 是一个非常灵活的网络请求库,它提供了很多扩展机制,让我们可以根据自己的需要来定制请求和响应处理逻辑。下面介绍一些常用的扩展机制。

Converter

Converter 用于将 HTTP 请求和响应的数据类型转换成 Java 对象。Retrofit 默认提供了两种 Converter:GsonConverterJacksonConverter,它们分别使用GsonJackson库将数据类型转换成Java对象。如果我们需要使用其他类型的转换库,也可以自定义 Converter 来实现。

下面是一个自定义 Converter 的示例:

public class MyConverter implements Converter<ResponseBody, MyObject> {

    private Gson gson;

    public MyConverter(Gson gson) {
        this.gson = gson;
    }

    @Override
    public MyObject convert(ResponseBody value) throws IOException {
        try {
            String json = value.string();
            MyObject obj = gson.fromJson(json, MyObject.class);
            return obj;
        } finally {
            value.close();
        }
    }
}

在上面的示例中,我们定义了一个MyConverter类,它实现了Converter接口,用于将ResponseBody类型的响应数据转换成MyObject类型的Java对象。在convert方法中,我们使用自己定义的转换逻辑来实现数据类型的转换。

Interceptor

Interceptor 用于对 HTTP 请求进行拦截和处理。在 Retrofit 中,我们可以通过 Interceptor 来对请求添加头信息、对响应进行缓存、打印请求日志等操作。Retrofit 提供了两种 Interceptor:OkHttpInterceptorRetrofitInterceptor,它们分别用于拦截 OkHttp 的请求和 Retrofit 的请求。我们也可以自定义 Interceptor 来实现自己的拦截逻辑。

下面是一个自定义 Interceptor 的示例:

public class MyInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        // 在这里可以对请求进行拦截和处理
        Request request = chain.request();
        Response response = chain.proceed(request);
        // 在这里可以对响应进行处理
        return response;
    }
}

在上面的示例中,我们定义了一个MyInterceptor类,它实现了Interceptor接口,用于对请求和响应进行拦截和处理。在intercept方法中,我们可以对请求进行处理,然后使用chain.proceed(request)方法将请求传递给下一个拦截器或处理器,最终获得响应结果并进行处理。

CallAdapter

CallAdapter 用于将 Call 对象转换成另一种类型的对象。在 Retrofit 中,我们可以通过 CallAdapter 将 Call 对象转换成 RxJava 的 Observable 对象,也可以将 Call 对象转换成 LiveData 对象。Retrofit 提供了两种CallAdapter:RxJavaCallAdapterLiveDataCallAdapter,它们分别用于将 Call 对象转换成 RxJava 的 Observable 对象和 LiveData 对象。我们也可以自定义 CallAdapter 来实现自己的转换逻辑。

下面是一个自定义 CallAdapter 的示例:

public class MyCallAdapter<T> implements CallAdapter<T, MyResult<T>> {
    @Override
    public Type responseType() {
        // 返回响应数据的类型
        return new ParameterizedTypeImpl(MyResult.class, new Type[]{T.class});
    }

    @Override
    public MyResult<T> adapt(Call<T> call) {
        // 在这里可以对Call对象进行处理,并返回自定义的结果对象
        try {
            Response<T> response = call.execute();
            return new MyResult<>(response.body(), response.code(), response.message());
        } catch (IOException e) {
            return new MyResult<>(e);
        }
    }
}

在上面的示例中,我们定义了一个MyCallAdapter类,它实现了CallAdapter接口,用于将Call对象转换成MyResult对象。在responseType方法中,我们返回了响应数据的类型,它是一个ParameterizedTypeImpl类型的对象,用于表示MyResult<T>类型。在adapt方法中,我们对Call对象进行处理,并返回自定义的MyResult对象,它包含了响应数据、状态码和错误信息。

总结

在本文中,我们深入分析了 Retrofit 的核心源码,特别是 Call 逻辑的实现细节,以及 Retrofit 的三个扩展机制:Converter、Interceptor 和 CallAdapter。

通过本文的学习,我们可以更加深入地理解 Retrofit 的工作原理,并可以根据需求自定义扩展 Retrofit 的功能。同时,本文提供了三个扩展机制的示例代码,可以帮助读者更加深入地了解 Retrofit 的扩展机制的使用。

猜你喜欢

转载自blog.csdn.net/zl_china/article/details/129448684
今日推荐