Can't change container ID of fragment

在學習kotlin的過程中,使用viewpager+fragment+BottomNavigationView想實現滑動切換頁面效果。

我在viewpager的onPageSelected中滑動就切換到指定頁,以爲是要進行fragment的add或者replace操作,然後看到各路大神紛紛推薦kotlin中優雅地添加fragment,就去跟着人家搞什麼擴展函數,具體是這篇文章:

使用Kotlin優雅的添加Fragment

結果就出現這個bug了,這個意思是說不能修改fragment的容器id。

然後捏,老半天百度,沒有解決。就在這時,突然看到別人的某某源碼分析,然後我才靜下心來分析下。哦,原來我在setAdapter設置了fragment數組以後,FragmentPagerAdapter人家自動就給你各種add事務操作了,具體我看到有這段,應該是初始化操作吧:

這裏可以看到就有各種事務操作了,這其中就有添加容器id,所以我再去add或者replace就不能更改containerId了。報錯原因是BackStackRecord源碼裏面有個方法是這麼寫的:
private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
        Class fragmentClass = fragment.getClass();
        int modifiers = fragmentClass.getModifiers();
        if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers) || fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)) {
            throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName() + " must be a public static class to be  properly recreated from" + " instance state.");
        } else {
            fragment.mFragmentManager = this.mManager;
            if (tag != null) {
                if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
                    throw new IllegalStateException("Can't change tag of fragment " + fragment + ": was " + fragment.mTag + " now " + tag);
                }

                fragment.mTag = tag;
            }

            if (containerViewId != 0) {
                if (containerViewId == -1) {
                    throw new IllegalArgumentException("Can't add fragment " + fragment + " with tag " + tag + " to container view with no id");
                }

                if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
                    throw new IllegalStateException("Can't change container ID of fragment " + fragment + ": was " + fragment.mFragmentId + " now " + containerViewId);
                }

                fragment.mContainerId = fragment.mFragmentId = containerViewId;
            }

            this.addOp(new BackStackRecord.Op(opcmd, fragment));
        }
    }

關於BackStackRecord這個類,可以看:Android進階——Fragment詳解之操作原理(三)

這個方法是執行添加fragment的操作,這裏在adapter的初始化方法中已經把container的id傳過去了,但是我可能腦子不知道短路還是咋的,又去佈局裏面放了個FrameLayout把viewPager給放進去了,把FrameLayout當作容器,人家本來是以ViewPager爲容器的,所以當然第二次的時候容器id不一樣了,就報錯了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章