在學習kotlin的過程中,使用viewpager+fragment+BottomNavigationView想實現滑動切換頁面效果。
我在viewpager的onPageSelected中滑動就切換到指定頁,以爲是要進行fragment的add或者replace操作,然後看到各路大神紛紛推薦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不一樣了,就報錯了。