前言
两层Fragment在某些情况下,内层Fragment会显示空白,这是一个比较常见的问题,百度到的一些帖子的方法有几种,但是在即的项目中,只有下面这种起了作用。最后附上在一篇帖子上看到的出现这种情况的原因(反正我看不懂)。
解法
Activity中使用replace切换:
private void initFirstFragment() {
course_fragment = new Fragment_main_course(); //双层Fragment的第一层,自定义的Fragment
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.course_main, course_fragment);
transaction.commit();
}
第一层Fragment添加:
private void initView(View view) {
tabLayout = view.findViewById(R.id.course_tab); //TabLayout
viewPager = view.findViewById(R.id.course_view_pager); //ViewPager
fragmentList = new ArrayList<>();
Fragment fragment_my_course = new Fragment_my_course();
Fragment fragment_all_course = new Fragment_all_course();
fragmentList.add(fragment_my_course);
fragmentList.add(fragment_all_course);
//重点就是下面这句话,一定要使用getChildFragmentManager()
adapter = new MyAdapter(getChildFragmentManager()); //自定义的适配器
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
下面的原因分析来源于:https://blog.csdn.net/bingospunky/article/details/51352400
原因剖析
产生空白的根本原因是往ViewGroup里添加子View失败。
概念
要解释明白这个过程首先需要明确几个概念,不知道各位看官是否明确,我先在这里列出来:
Fragment有一个叫mView的属性,就是这个Fragment对应的View,归根结底来说,Fragment就是代表一个View,FragmentManager操作Fragment就是操作Fragment所包含的View的添加、删除等,只是在他上面加了一些类似生命周期的控制。
FragmentManager这个类是管理Fragment的类,比如添加Fragment就是这个类来实现的,它添加一个Fragment的时候回让一个字符串与一个Fragment,如果这个字符串存在,就不会再添加这个Fragment。
FragmentManager这个类是与Actiity相关的,就是 * 一个FragmentAativity *,这一点很重要。
如果Fragment结合ViewPager使用,那么Fragment是被Adapter调用FragmentManager添加的,与Fragment对应的字符串是在Adapter里决定的,有Fragment类名相关的一个字符串。
约定
下面我们做如下约定:一个Activity通过一个ViewPager包含4个Fragment,分别命名为mFragment1,mFragment2,mFragment3,mFragment4,其中mFragment3通过ViewPager包含3个Fragment,分别命名为mFragment31,mFragment32,mFragment33。
操作:
1、显示mFragment1
2、显示mFragment3
3、显示mFragment1
4、显示mFragment3
在第4步的时候,内层的Fragment就会不显示。
解释
执行完第2步:mFragment3的onCreateView返回的View显示在屏幕上,里面添加了几个子View,子View就是Fragment对应的View,而且这几个子View是通过FragmentManager添加的,有String与之对应。
执行完第3步:mFragment3的onDestroyView方法会执行,代表着mView将被废弃,下次会通过onCreateView创建一个新的mView。在FragmentManager里mFragment32对应的字符串还存在,因为我们都知道FragmentPagerAdapter里的destroyItem没有被执行,至于destroyItem方法什么时候被执行你应该懂的。
执行完第4步:mFragment3的onCreateView方法被执行,返回的rootView显示在界面上,然后我们的代码里会通过FragmentPagerAdapter给这个rootView添加Fragment,也就是给这个rootView添加子View。在我们添加Fragment的过程中,因为在前面的过程中mFragment32对应的字符串已经存在了,所以添加mFragment32是失败的,即给rootView添加子View失败,所以界面里显示的就是空白。