ViewPager внутри Fragment теряет свое содержание, когда фрагмент переименован

У меня есть простой фрагмент с ViewPager.

Я использую обновленную библиотеку поддержки, v4 rev18!

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

java.lang.NullPointerException at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:569) at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211) at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1281) at android.view.View.dispatchRestoreInstanceState(View.java:12043) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2688) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2694) at android.view.View.restoreHierarchyState(View.java:12021) at android.support.v4.app.Fragment.restoreViewState(Fragment.java:425) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:949) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440) at android.os.Handler.handleCallback(Handler.java:615) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4800) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565) at dalvik.system.NativeStart.main(Native Method) 

Мой простой класс выглядит следующим образом и должен быть, на самом деле, прекрасным …

 public class RoutineDayFragment extends BaseFragment { private RoutinesActivity mParent = null; @InjectView(R.id.pager) MyViewPager pager = null; @InjectView(R.id.indicator) PagerSlidingTabStrip indicator = null; private FragmentStatePagerAdapter mAdapter = null; @Override public void onAttach(Activity activity) { super.onAttach(activity); mParent = ((RoutinesActivity) getBaseActivity()); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.view_pager, container, false); Views.inject(this, v); mAdapter = new FragmentStatePagerAdapter(getChildFragmentManager()) { @Override public int getCount() { if (mParent.getSharedData().selectedRoutine == -1) return 0; return mParent.getSharedData().routines.get(mParent.getSharedData().selectedRoutine).getRWorkoutDay().size(); } @Override public Fragment getItem(int pos) { return DayFragment.newInstance(pos); } @Override public CharSequence getPageTitle(int pos) { return Common.getString(R.string.day) + (pos + 1); } }; pager.setAdapter(mAdapter); indicator.setViewPager(pager); return v; } } 

Используйте AsyncTask для установки ViewPagerAdapter:

 private class SetAdapterTask extends AsyncTask<Void, Void, Void> { protected Void doInBackground(Void... params) { return null; } @Override protected void onPostExecute(Void result) { if(mAdapter != null) mViewPager.setAdapter(mAdapter); } } 

Назовите это так:

 mAdapter = new PageAdapter(getChildFragmentManager()); new SetAdapterTask().execute(); 

И сбросьте адаптер в onResume( ) вашего фрагмента.

UPDATE – Как вставить ViewPager внутри фрагмента?

Хорошо, вот оно. Я изменил пример Google Эффективной навигации, чтобы соответствовать вашим требованиям.

Что я создал?

  • Я создал простое приложение, содержащее MainActivity с ViewPager и 3 вкладками.
  • Каждая из этих вкладок представлена ​​фрагментом, который также содержит ViewPager.
  • ViewPager внутри фрагмента содержит 10 страниц.
  • Итак, у нас есть 3 "главных" вкладки / фрагменты, каждый из которых содержит еще 10 фрагментов.
  • Для демонстрационных целей я сделал невидимый просмотр ViewPager на верхнем уровне, поэтому вам нужно использовать вкладки для переключения между основными фрагментами (я создал CustomViewPager и внес некоторые изменения, чтобы удалить возможности просмотра ViewPagers)
  • ViewPager внутри основных фрагментов имеет возможность прокрутки, поэтому вы можете переключаться между субфрагментами и нажимать вкладки для переключения между основными фрагментами
  • Если вы нажмете суб-фрагмент, начнется новое действие.
  • Если вы вернетесь к старой активности при закрытии новой активности, состояние фрагментов и ViewPager будет сохранено.
  • При переключении основных фрагментов их состояние также сохраняется

Вот основная Activity.java

Он содержит два адаптера, один для основных фрагментов, один для вспомогательных фрагментов. Кроме того, это два класса Фрагмента, один – Фрагмент, содержащий ViewPager (основной-фрагмент), другой – суб-фрагмент (внутри вложенного ViewPager)

 public class MainActivity extends FragmentActivity implements ActionBar.TabListener { AppSectionsPagerAdapter mAppSectionsPagerAdapter; NonSwipeableViewPager mViewPager; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mAppSectionsPagerAdapter = new AppSectionsPagerAdapter(getSupportFragmentManager()); // Set up the action bar. final ActionBar actionBar = getActionBar(); actionBar.setHomeButtonEnabled(false); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Set up the ViewPager, attaching the adapter and setting up a listener for when the // user swipes between sections. mViewPager = (NonSwipeableViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mAppSectionsPagerAdapter); mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { actionBar.setSelectedNavigationItem(position); } }); // For each of the sections in the app, add a tab to the action bar. for (int i = 0; i < mAppSectionsPagerAdapter.getCount(); i++) { actionBar.addTab( actionBar.newTab() .setText(mAppSectionsPagerAdapter.getPageTitle(i)) .setTabListener(this)); } } @Override public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {} @Override public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) { // When the given tab is selected, switch to the corresponding page in the ViewPager. mViewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {} public static class AppSectionsPagerAdapter extends FragmentPagerAdapter { public AppSectionsPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { switch (i) { default: // The other sections of the app are dummy placeholders. Fragment fragment = new ViewPagerContainerFragment(); return fragment; } } @Override public int getCount() { return 3; } @Override public CharSequence getPageTitle(int position) { return "Tab " + (position +1); } } public static class ViewPagerAdapter extends FragmentPagerAdapter { public ViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { switch (i) { default: // The other sections of the app are dummy placeholders. Fragment fragment = new ViewPagerFragment(); Bundle b = new Bundle(); b.putString("key", "I am fragment nr " + i); fragment.setArguments(b); return fragment; } } @Override public int getCount() { return 10; } } /** * THIS FRAGMENT CONTAINS A VIEWPAGER */ public static class ViewPagerContainerFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.main_fragment, container, false); ViewPager pager = (ViewPager) rootView.findViewById(R.id.nestedViewPager); pager.setAdapter(new ViewPagerAdapter(getChildFragmentManager())); return rootView; } } /** * THIS FRAGMENT IS INSIDE THE VIEWPAGER */ public static class ViewPagerFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.sub_fragment, container, false); ((TextView) rootView.findViewById(R.id.tv1)).setText(getArguments().getString("key")); ((TextView) rootView.findViewById(R.id.tv1)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Intent intent = new Intent(getActivity(), CollectionDemoActivity.class); startActivity(intent); } }); return rootView; } } } 

activity_main.xml

 <com.example.android.effectivenavigation.NonSwipeableViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> 

main_fragment.xml

 <android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/nestedViewPager" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="24sp" /> 

sub_fragment.xml

 <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv1" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:textSize="50sp" /> 

Конечный результат выглядит следующим образом:

У нас есть 3 фрагмента верхнего уровня, каждый из которых содержит ViewPager с 10 фрагментами.

Введите описание изображения здесь