IllegalStateException:无法更改片段的标记是android:switcher现在android:switcher

我的活动使用TabLayout + ViewPager

在创build活动时启动3个静态选项卡+静态3个片段。 之后,我的应用程序获取一些远程对象,并在接收到这些远程对象时呈现额外的标签+碎片。 在任何时候,3个最初的标签+片段是第一个,然后是dynamic标签+片段。

崩溃报告通过Crashlytics,我无法复制它。

我的活动代码:

 @Override protected void onCreate(Bundle savedInstanceState) { boolean isAppRestarting = PrefUtils.getBoolean("app_restarting", false); if (isAppRestarting) { super.onCreate(null); this.savedInstanceState = null; } else { super.onCreate(savedInstanceState); this.savedInstanceState = savedInstanceState; } initSlidingTabs(); fetchSomeData(); // callback onDataFetched() } private void initSlidingTabs() { List<FragmentWithTitle> sdsTabs = new ArrayList<>(); if (savedInstanceState == null) { sdsTabs.add(new FragmentWithTitle(ShopFrag.newInstance(), "ShopFrag")); sdsTabs.add(new FragmentWithTitle(FragB.newInstance(), "FragB")); sdsTabs.add(new FragmentWithTitle(FragC.newInstance(), "FragC")); } else { Logger.i("There is saved instance state"); ArrayList<String> titles = savedInstanceState.getStringArrayList(TAB_TITLES); if (titles != null) { for (int i = 0; i < titles.size(); i++) { if (getFragment(i) != null) { sdsTabs.add(new FragmentWithTitle(getFragment(i), titles.get(i))); } } } } mTabsAdapter = new MyTabsAdapter(getSupportFragmentManager(), sdsTabs); // Assigning ViewPager View and setting the mTabsAdapter mViewPager = (ViewPager) findViewById(R.id.layoutViewPagerSlidingTabs); mViewPager.setAdapter(mTabsAdapter); mViewPager.setOffscreenPageLimit(2); mSlidingTabs = (CustomTextTabLayout) findViewById(R.id.tabs); mSlidingTabs.setupWithViewPager(mViewPager); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mTabsAdapter != null) { outState.putStringArrayList(TAB_TITLES, mTabsAdapter.getTitles()); } } private Fragment getFragment(int position) { Logger.d("getFragment " + position); return savedInstanceState == null ? mTabsAdapter.getItem(position) : getSupportFragmentManager() .findFragmentByTag(getFragmentTag(position)); } private String getFragmentTag(int position) { return "android:switcher:" + R.id.layoutViewPagerSlidingTabs + ":" + position; } /** Callback of fetchData() in onCreate() */ private void onDataFetched(List<ProductCategory> cats) { if (savedInstanceState == null) { if (cats != null) { for (ProductCategory cat : cats) { mTabsAdapter.addTab(new FragmentWithTitle(CategoryFrag.newInstance(cat.getSlugUrl()), cat .getLabel())); } } } else { Logger.d("There is saved instance state"); ArrayList<String> titles = savedInstanceState.getStringArrayList(TAB_TITLES); if (titles != null) { for (int i = 0; i < titles.size(); i++) { mTabsAdapter.addTab(new FragmentWithTitle(getFragment(i), titles.get(i))); } } } mTabsAdapter.notifyDataSetChanged(); } 

MyTabsAdapter(复制并从Internet上粘贴;不明白的saveState()方法,rest似乎没有什么特别的):

 public class MyTabsAdapter extends FragmentPagerAdapter { private List<FragmentWithTitle> mTabs = new ArrayList<>(); public MyTabsAdapter(FragmentManager fm, List<FragmentWithTitle> sdsTabs) { super(fm); this.mTabs = sdsTabs; } @Override public Fragment getItem(int position) { return mTabs.get(position).getFragment(); } @Override public CharSequence getPageTitle(int position) { return mTabs.get(position).getTitle(); } @Override public int getCount() { return this.mTabs.size(); } public int getItemPosition(Object object) { return POSITION_NONE; } /** * Prevent java.lang.IllegalStateException Fragment no longer exists for key android:target_state: index 5 * * @return */ @Override public Parcelable saveState() { return null; } public ArrayList<String> getTitles() { ArrayList<String> titles = new ArrayList<>(); for (int i = 0; i < mTabs.size(); i++) { titles.add((String) mTabs.get(i).getTitle()); } return titles; } public void addTab(FragmentWithTitle fragmentWithTitle) { mTabs.add(fragmentWithTitle); } } 

完整的堆栈跟踪:

 Fatal Exception: java.lang.IllegalStateException: Can't change tag of fragment ShopFrag{4dbb6e90 #0 id=0x7f1200dd android:switcher:2131886301:0}: was android:switcher:2131886301:0 now android:switcher:2131886301:9 at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:444) at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:426) at android.support.v4.app.FragmentPagerAdapter.instantiateItem(FragmentPagerAdapter.java:103) at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:1038) at android.support.v4.view.ViewPager.populate(ViewPager.java:1252) at android.support.v4.view.ViewPager.populate(ViewPager.java:1120) at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1646) at android.view.View.measure(View.java:17396) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5365) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410) at android.widget.LinearLayout.measureVertical(LinearLayout.java:695) at android.widget.LinearLayout.onMeasure(LinearLayout.java:588) at android.view.View.measure(View.java:17396) at android.support.v4.widget.DrawerLayout.onMeasure(DrawerLayout.java:1081) at android.view.View.measure(View.java:17396) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5365) at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139) at android.view.View.measure(View.java:17396) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5365) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410) at android.widget.LinearLayout.measureVertical(LinearLayout.java:695) at android.widget.LinearLayout.onMeasure(LinearLayout.java:588) at android.view.View.measure(View.java:17396) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5365) at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) at android.view.View.measure(View.java:17396) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5365) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1410) at android.widget.LinearLayout.measureVertical(LinearLayout.java:695) at android.widget.LinearLayout.onMeasure(LinearLayout.java:588) at android.view.View.measure(View.java:17396) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5365) at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2505) at android.view.View.measure(View.java:17396) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2175) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1316) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1513) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1200) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6401) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:803) at android.view.Choreographer.doCallbacks(Choreographer.java:603) at android.view.Choreographer.doFrame(Choreographer.java:573) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:789) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:157) at android.app.ActivityThread.main(ActivityThread.java:5335) at java.lang.reflect.Method.invokeNative(Method.java) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081) at dalvik.system.NativeStart.main(NativeStart.java) 

FragmentWithTitle:

 public class FragmentWithTitle { public FragmentWithTitle(Fragment mFragment, CharSequence mTitle) { this.fragment = mFragment; this.title = mTitle; } public Fragment getFragment() { return fragment; } public void setFragment(Fragment fragment) { this.fragment = fragment; } public CharSequence getTitle() { return title; } public void setTitle(CharSequence title) { this.title = title; } private Fragment fragment; private CharSequence title; } 

Solutions Collecting From Web of "IllegalStateException:无法更改片段的标记是android:switcher现在android:switcher"

FragmentPagerAdapter已经为你cachingFragments 。 每个片段分配一个标签,然后FragmentPagerAdapter尝试调用findFragmentByTag 。 如果findFragmentByTag的结果为null ,它只调用getItem()

您可能会收到此错误,因为您将相同的片段实例添加到列表中。 你应该为每个页面创build一个新的实例

示例表单文件:

 //... public static class MyAdapter extends FragmentPagerAdapter { public MyAdapter(FragmentManager fm) { super(fm); } @Override public int getCount() { return NUM_ITEMS; } @Override public Fragment getItem(int position) { return ArrayListFragment.newInstance(position); } } //.. 

请参阅: FragmentPagerAdapter

主线程: 从ViewPager中检索一个片段