Подтвердить что ты не робот

Загрузчик перезапускается при изменении ориентации

В документации Android для Loaders, найденной в http://developer.android.com/guide/components/loaders.html, говорится, что одно из свойств загрузчиков заключается в следующем:

Они автоматически подключаются к последнему курсору загрузчика при воссоздании после изменения конфигурации. Таким образом, им не нужно повторно запрашивать свои данные.

Следующий код, похоже, не отражает это поведение, создается новый Loader, заканчивается запрос ContentResolver, затем я поворачиваю экран и восстанавливается Загрузчик!

public class ReportFragment extends Fragment implements LoaderCallbacks<Cursor> {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getLoaderManager().initLoader(1, null, this);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_report, container, false);
        return v;
    }

    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
        Log.d("TEST", "Creating loader");
        return new CursorLoader(getActivity(), ResourcesContract.Reports.CONTENT_URI, null, null, null, null);
    }

    public void onLoadFinished(Loader<Cursor> arg0, Cursor arg1) {
        Log.d("TEST", "Load finished");
    }

    public void onLoaderReset(Loader<Cursor> arg0) {

    }

}

Вот результат моего логарифма:

08-17 16:49:54.474: D/TEST(1833): Creating loader
08-17 16:49:55.074: D/TEST(1833): Load finished
*Here I rotate the screen*
08-17 16:50:38.115: D/TEST(1833): Creating loader
08-17 16:50:38.353: D/TEST(1833): Load finished

Любая идея, что я делаю неправильно здесь?

EDIT:

Я должен отметить, что я строю Android Google API версии 8 и использую библиотеку поддержки v4.

2nd EDIT:

Это, скорее всего, связано с ошибкой в ​​библиотеке поддержки, посмотрите эту отправку ошибок, если вы хотите получить дополнительную информацию:

http://code.google.com/p/android/issues/detail?id=20791&can=5&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

4b9b3361

Ответ 1

onCreate() вызывается во время изменения ориентации экрана, так как активность уничтожается и воссоздается.

Если вы не загружаете много данных, это не помешает сделать, но вы можете попробовать следующее, если хотите (я его не тестировал, но теоретически думаю, что это сработает).

Объявить статическое логическое значение в верхнем глобальном классе. Я думаю, вам также понадобится статический курсор для ссылки

private static boolean dataDownloaded = false;
private static Cursor oldCursor;

Затем on onLoadFinished set dataDownloaded = true

Заменить onSaveInstanceState, чтобы сохранить логическое значение

@Override
protected void onSaveInstanceState(Bundle outSave) {
    outSave.putBoolen("datadownloaded", dataDownloaded);
    oldCursor = adapter.swapCursor(null);
}

и onCreate добавьте следующие

if (savedInstanceState != null) {
    this.dataDownloaded = savedInstanceState.getBoolean("datadownloaded", false);
}

настроить свой onCreateLoader

public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    CursorLoader cursorLoader;
    if (dataDownloaded) {
        cursorLoader = new CursorLoader(getActivity(),
            null, projection, null, null, null);
        cursorLoader.deliverResult(oldCursor);
    } else {
        CursorLoader cursorLoader = new CursorLoader(getActivity(),
            URI_PATH, projection, null, null, null);
    }

    return cursorLoader;
}

Ответ 2

Хотя это старый вопрос, я столкнулся с той же проблемой, что и OP. Используя загрузчик, мне нужно перезапустить его при переходе на новую активность, а затем обратно. Но в то же время я не хочу, чтобы загрузчик перезапускался, когда я поворачиваю экран телефона.

Я обнаружил, что это возможно в onRestart(), если вы перезапустите загрузчик, прежде чем вызывать его супер.

public class MainActivity extends AppCompatActivity implements
LoaderManager.LoaderCallbacks<Cursor> {

    ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ...

        //Initialize the loader.
        getSupportLoaderManager().initLoader(0, null, this);
    }

    @Override
    protected void onRestart() {
        //Restart the loader before calling the super.
        getSupportLoaderManager().restartLoader(LOADER_ID, null, this);

        super.onRestart();
    }

    ...

}

Ответ 3

До сих пор я обнаружил, что сохраняющий фрагмент Fragment.setRetainInstance(true) предотвращает воссоздание загрузчика при изменении ориентации с использованием библиотеки поддержки. Последние результаты погрузчика красиво доставлены в onLoadFinished(). Он работает, по крайней мере, когда активность управляет одним фрагментом, а фрагмент добавляется к активности с помощью FragmentTransaction.

Ответ 4

Хотя это немного старый вопрос, я хотел бы разместить здесь свои мнения.

Нет необходимости хранить дополнительную информацию в onSaveInstanceState

Структура автоматически подключается к последнему курсору загрузчика при воссоздании после изменения конфигурации. Таким образом, им не нужно повторно запрашивать свои данные.

Это означает, что в функции onCreate вам нужно вызвать loaderManager, только если значение savedInstanceState равно null

Пример:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if(savedInstanceState == null) {
        getLoaderManager().initLoader(1, null, this);
    }
}

Ответ 5

По-моему, вы неправильно поняли, что говорит документация. В документах говорится, что им не нужно повторно запрашивать свои данные, и это не так.

Попробуйте записать/вставить точку останова в свой метод ContentProvider#query()! Запрос будет вызываться только при запуске Activity, а не после изменения ориентации.

Но это не так для метода LoaderCallbacks#onCreateLoader(). Он будет вызываться после каждого изменения ориентации, но это не означает повторный запрос, он просто вызывает метод, поэтому вы можете изменить CursorLoader, если хотите.

Ответ 6

Вы можете просто проверить, существует ли уже уже установленный загрузчик. Затем вы можете перезапустить или перезапустить.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getLoaderManager().getLoader(LOADER_ID) == null) {
        getLoaderManager().initLoader(LOADER_ID, null, this);
    } else {
        getLoaderManager().restartLoader(LOADER_ID);
    }
}

Обычно вы передаете идентификатор своему загрузчику, чтобы впоследствии ссылаться на него через диспетчер загрузчика.

Надеюсь, это поможет!