2013-06-22 3 views
8

У меня есть действие, содержащее фрагмент «список», который при нажатии на один из его элементов заменит себя на «контент». Когда пользователь использует кнопку «Назад», он снова возвращается к фрагменту «списка».
Проблема в том, что фрагмент находится в состоянии по умолчанию, независимо от того, что я пытаюсь сохранить данные.Как сохранить данные фрагмента после транзакций backstack?

факты:

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

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

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

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

Примечание: возможно related/duplicate question

+0

Прямо сейчас единственный вариант, который у меня есть: 'isFromBackStack = getActivity(). GetSupportFragmentManager(). GetBackStackEntryCount()> 0'. Я хотел бы, чтобы у меня было что-то более чистое, для меня это похоже на хак. Кроме того, я не получаю «Bundle» из предыдущего экземпляра фрагмента. –

ответ

8

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

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. Но принципы одинаковы.

+0

Ничего себе. Я просто изучаю Android, поэтому я подозреваю, что у меня что-то не хватает. Может быть, я должен прочитать книгу. Я не мог заставить данные сохраняться на протяжении всего жизненного цикла моего фрагмента. Но это делает трюк. Спасибо – terary

+1

Вместо сохранения состояния в onDestroyView для случая backstack вы можете использовать FragmentManager's saveFragmentInstanceState() до того, как вы его удалите/замените. Это вызовет функциюSaveInstanceState(). Это позволяет сохранить код сохранения состояния в одном месте. –

+0

У меня есть аналогичный подход к этому, когда мне нужно сохранить список, который был ранее загружен при замене «фрагмента». Вы знаете, может ли это вызвать проблемы с памятью? – jlively