Я использую OkHttp, и я только что столкнулся с этой проблемой.
Для первой части @ thucnguyen был на правильном пути .
Это произошло, когда вы вызываете getActivity () в другом потоке, завершившемся после удаления фрагмента.Типичным случаем является вызов getActivity () (например, для тоста), когда HTTP-запрос завершен (например, в onResponse).
Некоторые вызовы HTTP выполнялись даже после того, как действие былобыл закрыт (поскольку выполнение HTTP-запроса может занять некоторое время).Затем я через HttpCallback
попытался обновить некоторые поля Fragment и получил исключение null
при попытке getActivity()
.
http.newCall(request).enqueue(new Callback(...
onResponse(Call call, Response response) {
...
getActivity().runOnUiThread(...) // <-- getActivity() was null when it had been destroyed already
IMO, решение состоит в том, чтобы предотвращать обратные вызовы, когдафрагмент больше не жив (и это не только с Okhttp).
Исправление: предотвращение.
Если вы посмотрите на жизненный цикл фрагмента (подробнее здесь ), вы заметите, что есть методы onAttach(Context context)
и onDetach()
.Они вызываются после того, как фрагмент принадлежит к действию, и непосредственно перед тем, как он перестает быть таким, соответственно.
Это означает, что мы можем предотвратить этот обратный вызов, управляя им в методе onDetach
.
@Override
public void onAttach(Context context) {
super.onAttach(context);
// Initialize HTTP we're going to use later.
http = new OkHttpClient.Builder().build();
}
@Override
public void onDetach() {
super.onDetach();
// We don't want to receive any more information about the current HTTP calls after this point.
// With Okhttp we can simply cancel the on-going ones (credits to https://github.com/square/okhttp/issues/2205#issuecomment-169363942).
for (Call call : http.dispatcher().queuedCalls()) {
call.cancel();
}
for (Call call : http.dispatcher().runningCalls()) {
call.cancel();
}
}