Я використовую OkHttp, і я щойно стикався з цією проблемою.
З першої частини @thucnguyen був на правильному шляху .
Це сталося, коли ви викликаєте getActivity () в іншому потоці, який закінчився після видалення фрагмента. Типовим випадком є виклик getActivity () (наприклад, для Toast) після завершення запиту HTTP (наприклад, у OnResponse).
Деякі дзвінки HTTP виконувались навіть після того, як активність була закрита (оскільки завершення запиту HTTP може зайняти деякий час). Я потім, HttpCallback
спробувавши оновити деякі фрагменти поля і отримав 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();
}
}
getActivity()
. Крім того, як ви створюєте фрагмент? Чи є він у вашому layout.xml?