Иногда не получается обратный вызов 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(), но он будет более эффективным.

Ответ 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 );

Ответ 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);
    }