ViewPager с вложенными фрагментами?

Моя проблема

Согласно документам Google:

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

Fragment videoFragment = new VideoPlayerFragment(); FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); transaction.add(R.id.video_fragment, videoFragment).commit(); 

Поэтому я создал свой собственный PageFragment . И мой PageFragmentAdapter состоит из 3 страниц PageFragment . У меня также есть шесть фрагментов: Fragment1 , Fragment2 , Fragment3 , FragmentA , FragmentB , FragmentC . В моей MainActivity я инициализирую свои шесть фрагментов, мой ViewPager и его PageFragmentAdapter (которые инициализируют три PageFragment для себя).

Затем я использую этот метод, чтобы прикрепить мои Fragment1 , Fragment2 , Fragment3 к каждой странице (к каждому PageFragment ) PageFragmentAdapter :

 PageFragmentAdapter tPageFragmentAdapter = new PageFragmentAdapter(getSupportFragmentManager()); tPageFragmentAdapter.setFirstPage(tFragment1); tPageFragmentAdapter.setSecondPage(tFragment2); tPageFragmentAdapter.setThirdPage(tFragment3); 

Я могу извлечь (через методы в PageFragmentAdapter ) фрагменты и сделать «вложенный фрагмент» в свой PageFragment (конечно, в onCreate() ) следующим образом:

 getChildFragmentManager().beginTransaction() .add(R.id.framelayout_history, mFragment) .addToBackStack(null) .commit(); 

Примечание. Я использую параметр PageFragment.setNestedFragment() чтобы установить в нем mFragment .

И он отлично работает! Это поможет мне (но эта история не об этом) просто заменить фрагменты в ViewPager, например:

 tPageFragmentAdapter.replaceFirstPage(tFragmentA); 

Но у меня одна огромная проблема. Снова документы Google:

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

Как вы можете видеть, PageFragmentAdapter может уничтожить каждый мой PageFragment и, конечно, его вложенный фрагмент. И когда он будет воссоздан, он будет иметь значение NULL вместо mFragment . Я пытаюсь сохранить его с помощью getChildFragmentManager().putFragment() а затем получить его с помощью getChildFragmentManager().getFragment() . Но это не сработало.

Вопрос

Поэтому мой вопрос: как сохранить мой вложенный фрагмент в родительском фрагменте? Является ли это возможным?

Я был бы очень признателен за вашу помощь. Алекс. PS Очень жаль моего английского 🙂

РЕДАКТИРОВАТЬ

Thx @ AndroidBegin.com за ответ!

Это, кажется, ошибка в недавно добавленной поддержке вложенных фрагментов. В основном, ребенок FragmentManager заканчивается сломанным внутренним состоянием, когда он отделен от действия. Кратковременный обходной путь, который исправил его для меня, заключается в добавлении следующего к onDetach () каждого фрагмента, который вы называете getChildFragmentManager ():

 @Override public void onDetach() { super.onDetach(); try { Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager"); childFragmentManager.setAccessible(true); childFragmentManager.set(this, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } 

Попробуйте это на своем фрагменте.

 public class Fragment2 extends SherlockFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.viewpager_main, container, false); // Locate the ViewPager in viewpager_main.xml ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewPager); // Set the ViewPagerAdapter into ViewPager mViewPager.setAdapter(new ViewPagerAdapter(getChildFragmentManager())); return view; } @Override public void onDetach() { super.onDetach(); try { Field childFragmentManager = Fragment.class .getDeclaredField("mChildFragmentManager"); childFragmentManager.setAccessible(true); childFragmentManager.set(this, null); } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } } 

Источник: http://www.androidbegin.com/tutorial/actionbarsherlock-side-menu-navigation-nested-viewpager-fragment-tabs-tutorial/