Как сохранить фрагмент данных после backstack транзакций?

у меня есть действие, содержащее фрагмент "list", который при нажатии на один из его элементов заменит себя на фрагмент "content". Когда пользователь использует кнопку "назад", он снова возвращается к фрагменту "список".
Проблема в том, что фрагмент находится в состоянии по умолчанию, независимо от того, что я пытаюсь сохранить данные.

факты:

  1. оба фрагмента создаются через public static TheFragment newInstance(Bundle args), setArguments(args) и Bundle args = getArguments()
  2. оба фрагмента находятся на же уровне, который находится непосредственно внутри FrameLayout из родительского действия (то есть не вложенных фрагментов)
  3. я не хочу называть setRetainInstance, потому что моя деятельность-это поток master/detail, который имеет макет панели 2 на больших экранах. 7 " таблетки имеют 1 панель в портрете и 2 панели в ландшафте. Если я сохраню экземпляр фрагмента "list", он (я думаю) испортит все с вращениями экрана
  4. когда пользователи щелкают элемент во фрагменте "список", фрагмент " содержимое отображается через FragmentTransaction#replace(int, Fragment, String), С тем же идентификатором, но с другим тегом
  5. я переопределил onSaveInstanceState(Bundle), но это не всегда вызывается фреймворком, как в формате doc: " есть много ситуаций, когда фрагмент может быть в основном снесен (например, когда он помещен в задний стек без отображения пользовательского интерфейса), но его состояние не будет сохранено до тех пор, пока его собственная активность фактически не должна сохранить свое состояние."
  6. я использую поддержку библиотека

из пули 5 выше, я думаю, что устройства низкого класса, которые должны восстановить память после транзакции фрагмента, могут вызвать Fragment#onSaveInstanceState(Bundle). Однако на моих тестовых устройствах (Galaxy Nexus и Nexus 7) платформа не вызывает этот метод. Так что это недопустимый вариант.

Итак, как я могу сохранить некоторые данные фрагмент? пакет передан Fragment#onCreate, Fragment#onActivityCreated, etc. всегда null.

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

Примечание: возможно обзоры/дублирую вопрос

1 ответов


это не кажется правильным, но вот как я делал:

public class MyActivity extends FragmentActivity {
    private Bundle mMainFragmentArgs;

    public void saveMainFragmentState(Bundle args) {
        mMainFragmentArgs = args;
    }

    public Bundle getSavedMainFragmentState() {
        return mMainFragmentArgs;
    }

    // ...
}

и в главном фрагмент:

public class MainFragment extends Fragment {
    @Override
    public void onActivityCreated(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle args = ((MyActivity) getActivity()).getSavedMainFragmentState();

        if (args != null) {
            // Restore from backstack
        } else if (savedInstanceState != null) {
            // Restore from saved instance state
        } else {
            // Create from fragment arguments
            args = getArguments();
        }

        // ...
    }

    // ...

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        Bundle args = new Bundle();
        saveInstance(args);
        ((MyActivity) getActivity()).saveMainFragmentState(args);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        saveInstance(outState);
    }

    private void saveInstance(Bundle data) {
        // put data into bundle
    }
}

это работает!

  • если вернуться из backstack, фрагмент использует параметры, сохраненные в onDestroyView
  • если вернуться из другого приложения / процесса / из памяти, фрагмент восстанавливается из onSaveInstanceState
  • при первом создании фрагмент использует параметры, заданные в setArguments

все события освещаются, и самая свежая информация всегда хранится.

это на самом деле сложнее, это interface - на основе, слушатель не зарегистрирован из onAttach/onDetach. Но принципы те же.