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