Иногда не получается обратный вызов onCreateLoader после вызова initLoader
У меня есть действие, которое вызывает initLoader, когда оно создано, чтобы загрузить данные, которые будет отображаться в активности. Обычно это прекрасно работает. У меня есть точки останова, чтобы видеть порядок, что все происходит. Сначала я вызываю initLoader, затем получаю обратный вызов OnCreateLoader, затем обратный вызов OnLoadFinished, тогда все отлично.
Однако я заметил, что если бы я изменил ориентацию на своем Android, я не получаю обратный вызов OnCreateLoader или обратный вызов OnLoadFinished, в результате чего на странице не отображаются данные. Я все еще получаю свою точку останова на вызове initLoader, поэтому я знаю, что это происходит, но я не получаю сообщение об ошибке, и я не могу найти никакой документации, объясняющей, почему я не получил обратный вызов после вызова initLoader.
Интересно, что я получаю обратные вызовы, если вернусь к исходной ориентации.
Итак, суммируем:
Я начинаю работу в портретной ориентации
- Я вызываю initLoader
- Я получаю onCreateLoader и onLoadFinished обратные вызовы
Затем я перехожу к пейзажу
- Я вызываю initLoader
- no onCreateLoader или onLoadFinished callbacks
Я возвращаюсь к портрету
- Я вызываю initLoader
- Я получаю onCreateLoader и onLoadFinished обратные вызовы
Точно так же, если я начинаю работу в ландшафтном режиме, я получаю обратные вызовы. Тогда, если я переключусь на портрет, я этого не сделаю. Затем, если я вернусь к пейзажу, я снова получаю обратные вызовы.
Кто-нибудь знает, что происходит?
Ответы
Ответ 1
Мы видели эту же проблему с фрагментами в ViewPager. Похоже, что загрузчики не будут правильно активированы снова, когда фрагмент будет возобновлен. Фактически, когда фрагмент приостановлен, наш CursorLoader больше не получает обратные вызовы ContentObserver, как я ожидал.
Наше решение - вызвать restartLoader(), который выгружает предыдущее содержимое и перезагружает данные. Это будет иметь тот же чистый эффект, что и destroyLoader(); initLoader(), но он будет более эффективным.
Ответ 2
Вам нужно будет вызвать initLoader в вашем onCreate
По аналогичной проблеме и дополнительной информации смотрите LoaderCallbacks.onLoadFinished не вызывается, если изменение ориентации происходит во время запуска AsyncTaskLoader
Ответ 3
Я отслеживаю эту проблему
Начальное создание (OnActivityCreated)
initLoader → OnCreateLoader → OnOnStartLoading → OnLoadFinished
Изменение ориентации - снова активировано OnActivityCreated
initLoader - OnLoadFinished (без загрузки каких-либо данных!) - ошибка.
Единственным обходным решением, которое я нашел, является вызов destroyLoader() непосредственно перед init. Это приведет к возникновению правильной последовательности Create/Start/Finished.
Что, по-видимому, происходит, это код initLoader, написанный, чтобы предположить, что фрагмент не будет разрушен во время изменения ориентации, что, конечно, не так, как работает остальные андроиды.
Ответ 4
У меня было что-то очень похожее с адаптерами курсора в фрагментах при изменении ориентации. initloader был вызван в onCreateView (также пытался onStart и onResume), но onCreatLoader, а также другие методы обратного вызова загрузчика никогда не вызывались. Также обратите внимание, что в моем случае фрагмент содержался в представлении пейджера.
Итак, сначала были созданы активность и просмотр пейджера и фрагментов, и все сработало. При изменении ориентации, хотя списки в моих фрагментах не получат данные. Снова изменив ориентацию и данные вернулись.
В моем случае исправление менялось:
getActivity().getLoaderManager().initLoader( 0, null, this );
Я изменил его на
getLoaderManager().initLoader( 0, null, this );
Ответ 5
Это старый вопрос, но, возможно, кто-то может по-прежнему заботиться...
У меня была такая же проблема, и я смог ее исправить. Здесь ссылка: onCreateLoader не вызывается при изменении ориентации
Ответ 6
Я потратил несколько недель на отслеживание этой проблемы. Он устал помещать предыдущий фрагмент в свой новый фрагмент.
Наконец исправлено.
В моем методе onCreate(), в котором реализован фрагмент LoaderManager, я сделал это
getLoaderManager().initLoader(0, null, this);
if(!getLoaderManager().getLoader(0).isReset()) {
getLoaderManager().restartLoader(0, null, this);
}
Он работает, когда новый загрузчик не был активирован должным образом.
Ответ 7
У меня была эта проблема в последнее время, и я хотел бы представить свое решение.
Я обнаружил, что этого достаточно просто:
Loader<Cursor> loader = getActivity().getLoaderManager().getLoader(LOADERID);
if (loader == null) {
getActivity().getLoaderManager().initLoader(LOADERID, null, this);
} else {
getActivity().getLoaderManager().restartLoader(LOADERID, null, this);
}