14

Retrofit v2 API 仕様を読みましたが、カスタム レトロフィット インターフェイスから返された Call クラスで cancel() メソッドを呼び出すと、渡された Callback を null に設定する必要があります。

cancel() は、応答が受信された後はノーオペレーションです。それ以外の場合、メソッドはすべてのコールバックを null に設定します (したがって、匿名で宣言されている場合は、外側のクラスへの強い参照が解放されます)。

コードを調べてみると、キャンセルが呼び出されたときに Callback が明示的に null に設定されていることがわかりません。コールバックがOkHttpCallクラスで参照されていることがわかります(ただし、明示的に格納されていません)。cancel を呼び出すと、キャンセルの HTTP 側を処理する RealCall クラスで cancel が呼び出されますが、AsyncCall クラスに保存されているコールバック (Dispatcher クラスの readyAsyncCalls および runningAsyncCalls キューに置かれている) には関係しません。私にはなじみのないコードなので、何かが欠けている可能性があります。

call オブジェクトで cancel() を呼び出すと、渡した Callback への参照が削除されるため、メモリ リークが発生しないことを誰かが自信を持って確認できますか?

簡略化されたコード例:

@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();
}
4

1 に答える 1