2013-05-09 2 views
2

В моем приложении я имею следующую архитектуру:Сохранение состояния фрагмента

MainActivity 
|_ FirstFragment 
| |_ GridFragment 
| |_ MapFragment 
| 
|_ SecondFragment 
| 
|_ ThirdFragment 

Обратите внимание, что:

  • MainActivity использует ActionBarSherlock и SlidingMenu.
  • SlidingMenu переключатели между фрагментами (FirstFragment, SecondFragment, ThirdFragment).
  • FirstFragment создает кнопку в панели действий для переключения между сеткой и карта режим. Это значит, чтобы переключаться между его субфрагментами.

То, что я хочу достичь

Мне нужно фрагменты должны сохранять свое состояние при переключении между ними. Это, если я в FirstFragment, а затем выберите режим карты (показать MapFragment субфрагмент), а из меню слайдов выберите другой вариант и вернитесь, Я должен снова увидеть карту. Прямо сейчас, это сброс каждого фрагмента при выборе его раздела из меню слайдов.

Это неудивительно, поскольку на данный момент я совершаю транзакции с new FirstFragment() при нажатии на пункты меню.

Тем не менее, я сначала попытался иметь ссылки на каждый фрагмент в своем родителе. Например, у MainActivity было три члена фрагментов, которые при совершении транзакций были проверены, если они существуют ранее, и при необходимости создаются. Это работало нормально, пока я не добавил второй уровень фрагментов, затем он начал бросать исключения при совершении транзакции (говоря, что активность была уничтожена).

Как вы, возможно, заметили, я далек от того, чтобы быть экспертом по Android и вам нужно руководствоваться этой темой.

Как сохранить состояния фрагментов без ссылки для каждого из них?

+0

* ... как на данный момент я совершаю транзакции с новым FirstFragment() при нажатии на пункты меню. * - когда пользователь вносит изменения в хранилище 'FirstFragment', которые изменяются в' Activity' выровняйте логическое целое поле (или вы можете сохранить его в статическом булевом флаге в FirstFragment, поскольку у вас есть только два варианта). Когда создается новый экземпляр FirstFragment, он проверяет действие или этот логический флаг и создает правильный вложенный фрагмент на основе значения флага. – Luksprog

+0

Как вы обрабатываете фрагменты второй глубины (сетка и карта)? Вы использовали getChildFragmentManager() для их управления? В моем случае мне удалось выполнить две вкладки (вкладка на вкладке), используя getFragmentManager() для вкладки первой глубины и getChildFragmentManager() для вкладки второй глубины. – kingori

+0

@kingori Да, я использую 'getChildFragmentManager()' внутри 'FirstManager'. –

ответ

3

Следующая вещь, которую я попробовал после размещения вопрос в том, чтобы избежать сохранения фрагментов в локальных переменных внутри контейнера и использовать FragmentManager.getFragmentByTag() для доступа к ним в любой момент времени, но проблема сохраняется, поскольку FragmentTransaction.replace() разрушал фрагменты.

Мое решение

Как Luksprog отметил в своем комментарии, я должен был управлять всеми фрагментами вручную. Чтобы достичь этого, мне пришлось вернуться к моему прежнему подходу, где у меня были локальные переменные для каждого фрагмента. Затем MainActivity выполняет следующие действия:

  • Создает три фрагмента.

    this.firstFragment = new FirstFragment(); 
    this.secondFragment = new SecondFragment(); 
    this.thirdFragment = new ThirdFragment(); 
    
  • Прикрепите три фрагмента и скройте все из них, кроме начальной секции.

    getSupportFragmentManager() 
        .beginTransaction() 
        .add(R.id.content_frame, this.firstFragment) 
        .add(R.id.content_frame, this.secondFragment) 
        .add(R.id.content_frame, this.thirdFragment) 
        .hide(this.secondFragment) 
        .hide(this.thirdFragment) 
        .commit(); 
    
  • Для переключения содержимого, SlideMenu зовет эту функцию:

    public void switchContent(Fragment newContent) { 
        if (newContent != null) { 
         getSupportFragmentManager() 
         .beginTransaction() 
         .detach(this.firstFragment) 
         .detach(this.secondFragment) 
         .detach(this.thirdFragment) 
         .attach(newContent) 
         .commit(); 
    
         // Restore menu open gesture if map is not present 
         if (!(newContent instanceof firstFragment) && getSlidingMenu().getTouchModeAbove() != SlidingMenu.TOUCHMODE_FULLSCREEN) 
          getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); 
    
         // Set menu open gesture if map is present 
         if (newContent instanceof firstFragment && firstFragment.currentFragment == FirstFragment.MAP_FRAGMENT) 
          getSlidingMenu().setTouchModeAbove(SlidingMenu.TOUCHMODE_NONE); 
    
         getSlidingMenu().showContent(); 
        } 
    } 
    

Затем фрагменты которого субфрагментами (FirstFragment) делает то же самое, но:

  • Используется getChildFragmentManager() вместо getSupportFragmentManager().
  • Используется show() и hide() для замены контента, поскольку при использовании detach() и attach() карта не сохраняла его координаты.
+0

В общем, это звучит как антипаттерн, но на самом деле это работает, и я не нашел других решений проблемы. – Antoniossss

Смежные вопросы