ViewPager2子Fragment使用getChildFragmentManager报错原因及适用场景咨询
一、为什么会抛出找不到视图的异常
getChildFragmentManager()是当前Fragment专属的子Fragment管理器,它的作用范围仅限当前Fragment自己的布局内部。你要操作的R.id.Navigation_Main_Layout是在Main Activity的布局里,属于Activity的视图层级,不在Fragment A/B的布局范围内。
用Fragment A/B的getChildFragmentManager()执行事务时,它只会在自己的布局树里搜索目标ID,自然找不到Activity里的视图,所以触发IllegalArgumentException。
而getActivity().getSupportFragmentManager()是Activity的全局Fragment管理器,覆盖整个Activity的视图层级,所以能定位到这个布局ID,事务正常执行。
至于getParentFragmentManager(),它指向的是Fragment A/B的父管理器——也就是Fragment 1的getChildFragmentManager()(因为Fragment A/B是ViewPager的子Fragment,由Fragment 1的子管理器创建),这个管理器的作用范围是Fragment 1的布局内部,同样碰不到Activity里的视图,所以也会报错。
二、什么时候该用getChildFragmentManager()
只有当你需要在当前Fragment自己的布局容器中添加、替换子Fragment时,才应该用getChildFragmentManager():
- 举个例子:如果Fragment A的布局里有一个
FrameLayout(id为R.id.fragment_a_inner_container),要在这个容器里加载一个子Fragment,这时用getChildFragmentManager()才是正确的,因为这个容器属于Fragment A的视图层级。 - 如果要操作的容器属于Activity,或者父Fragment的布局,就得对应使用Activity的管理器,或者父Fragment的管理器(
getParentFragmentManager())。
附:相关代码与报错信息
报错信息
java.lang.IllegalArgumentException: No view found for id 0x7f080123 (com.example.app:id/Navigation_Main_Layout) for fragment TargetFragment{xxxx-xxxx}
报错的事务代码
// Fragment A/B中的代码 getChildFragmentManager().beginTransaction() .replace(R.id.Navigation_Main_Layout, new TargetFragment()) .commit();
正常运行的事务代码
// Fragment A/B中的代码 getActivity().getSupportFragmentManager().beginTransaction() .replace(R.id.Navigation_Main_Layout, new TargetFragment()) .commit();
Main Activity布局文件(含目标视图ID)
<!-- activity_main.xml --> <androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/Drawer_Layout" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 事务要操作的主内容容器 --> <FrameLayout android:id="@+id/Navigation_Main_Layout" android:layout_width="match_parent" android:layout_height="match_parent" /> <com.google.android.material.navigation.NavigationView android:id="@+id/Navigation_View" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" /> </androidx.drawerlayout.widget.DrawerLayout>
内容的提问来源于stack exchange,提问作者Ritu

