改造 v2 Call.cancel() 是否删除了回调?

2022-09-04 04:49:52

我已经在 Retrofit v2 API 规范中读到,在从自定义改造接口返回的 Call 类上调用 cancel() 方法应将传入的回调设置为 null。

cancel() 是收到响应后的 no-op。在所有其他情况下,该方法会将任何回调设置为 null(因此,如果匿名声明,则释放对封闭类的强引用)

通过代码,我看不到调用unance时回调显式设置为null。我可以看到回调在OkHttpCall类中被引用(尽管没有显式存储)。调用取消将反过来在 RealCall 类上调用取消,该类负责取消的 Http 端,但不关心 AsyncCall 类中存储的回调(该类放在 readyAsyncCalls 中,并在 Dispatcher 类中运行 AsyncCalls 队列中)。这对我来说是不熟悉的代码,所以我可能会错过一些东西。

有人可以自信地确认在我的调用对象上调用unsub()将删除对我传入的回调的引用,这样我就不会泄漏内存吗?

简化代码示例:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    final Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    api = retrofit.create(Api.class);
}

@Override
public void onStart() {
    super.onStart();
    call = api.getPokedex();
    call.enqueue(new Callback<Pokedex>() {
        @Override
        public void onResponse(Call<Pokedex> call, Response<Pokedex> response) {
            populate(response.body());
        }

        @Override
        public void onFailure(Call<Pokedex> call, Throwable t) {
            error(t.getMessage());
        }
    });
}

@Override
public void onStop() {
    call.cancel();
    super.onStop();
}

答案 1

对 CallBack 的引用不会被删除,如果您根据文档调用#取消调用取消调用

  /**
   * Cancel this call. An attempt will be made to cancel in-flight calls, and if the call has not
   * yet been executed it never will be.
   */
  void cancel();

无论如何,在取消调用后,回调被称为onFailure方法。

public interface Callback<T> {
  /**
   * Invoked when a network exception occurred talking to the server or when an unexpected
   * exception occurred creating the request or processing the response.
   */
  void onFailure(Call<T> call, Throwable t);
}

在代码中测试 Call#isCanceled() 的最简单方法。

 @Override
        public void onFailure(Call<Pokedex> call, Throwable t) {
            Log.w(TAG, "Call is canceled: " + call.isCancelled());
            error(t.getMessage());
        }

答案 2

推荐