IllegalStateException: Can't change tag of fragment was android:switcher now android:switcher

五迷三道 提交于 2019-12-04 16:21:04

问题


My activity uses TabLayout + ViewPager.

The number of tabs and pages here are dynamic depending on the data fetch from the server.

The crash are reported via Crashlytics, I'm not able to replicate it.

My Activity code:

@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(); // see onDataFetched() below
    }

private void initSlidingTabs() {
        List<FragmentWithTitle> sdsTabs = new ArrayList<>();
            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);

        mViewPager = (ViewPager) findViewById(R.id.layoutViewPagerSlidingTabs);
        mViewPager.setAdapter(mTabsAdapter);
        mViewPager.setOffscreenPageLimit(2);

        mSlidingTabs = (TabLayout) 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) {
        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<AbcObject> abcObjects) {
        if (savedInstanceState == null) {
            if (abcObjects != null) {
                for (AbcObject abcObject : abcObjects) {
                    mTabsAdapter.addTab(new FragmentWithTitle(AbcFragment.newInstance(), abcObject.getTitle()));
                }
            }
        } 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:

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);
    }
}

Full stacktrace:

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;
}

回答1:


The FragmentPagerAdapter already caches the Fragments for you. Each fragment is assigned a tag, and then the FragmentPagerAdapter tries to call findFragmentByTag. It only calls getItem() if the result from findFragmentByTag is null.

You're probably getting this error because you're adding the same fragment instance to the list. You should create a new instance for each page.

Example form document :

//...
      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);// IMPORTANT
            }
        }
    //..

Refer :FragmentPagerAdapter

Main thread : Retrieve a Fragment from a ViewPager



来源:https://stackoverflow.com/questions/41974251/illegalstateexception-cant-change-tag-of-fragment-was-androidswitcher-now-and

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!