Fragment采坑记录

2019-03-27  本文已影响0人  人丑茶凉

解决问题:复现bug,会发现除嵌套的Fragment外,其他的Fragment显示和点击事件均正常,也就是说问题可以锁定在嵌套的Fragment的宿主Fragment。 问题范围锁定后,查阅资料,发现与FragmentManager(Fragment管理类)有关。回看代码, 问题在对象FragmentTransaction,发现宿主Activity和宿主Fragment获取对象FragmentTransaction的方式均为 getSupportFragmentManager().beginTransaction(),而宿主Fragment需要使用getChildFragmentManager().beginTransaction(), 替换代码,重新运行,问题解决; 总结:Activity中获取对象FragmentTransaction,统一使用getSupportFragmentManager().beginTransaction(); Fragment中获取对象FragmentTransaction,统一使用getChildFragmentManager().beginTransaction()。

补充(语言有些书面难懂,不求甚解者可忽略):关于getChildFragmentManager() 和 getSupportFragmentManager() getChildFragmentManager()是fragment中的方法, 返回的是管理当前fragment内部子fragments的manager. getSupportFragmentManager()在activity和fragment中都有. 在activity中, 方法用getSupportFragmentManager(), 返回的是管理activity中fragments的manager. 在fragment中, 还叫getSupportFragmentManager(), 返回的是把自己加进来的那个manager. 也即, 如果fragment在activity中, fragment.getFragmentManager()得到的是activity中管理fragments的那个manager. 如果fragment是嵌套在另一个fragment中, fragment.getFragmentManager()得到的是它的parent的getChildFragmentManager(). 总结就是: getFragmentManager()是本级别管理者, getChildFragmentManager()是下一级别管理者. 这实际上是一个树形管理结构.

问题分析:内存不足时,宿主Activity会被异常关闭,当再次打开时,Activity重新创建, 但与Viewpager结合使用的Fragment生命周期异常,viewpager的适配器继承自FragmentPagerAdapter,页面虽然被恢复, 但Fragment内的数据均被回收,所以Fragment会出现空指针。

解决问题:经不断探索目前有两种解决方案。

第一种,在Fragment集合放入适配器之前, 利用getSupportFragmentManager().getFragments(),获取到新的List<Fragment>, 然后遍历并删除这个集合内的所有的Fragment对象, 删除Fragment对象的代码:

getSupportFragmentManager().beginTransaction().remove(saveFragmentList.get(i)).commit()。
            List<Fragment> saveFragmentList = getSupportFragmentManager().getFragments();
            for (int i = 0; i < saveFragmentList.size(); i++) {
                getSupportFragmentManager().beginTransaction().remove(saveFragmentList.get(i)).commit();
            }
            list1Fragment = new List1Fragment();
            list2Fragment = new List2Fragment();
            list3Fragment = new List3Fragment();
            list4Fragment = new List4Fragment();
            fragmentList.clear();
            fragmentList.add(list1Fragment);
            fragmentList.add(list2Fragment);
            fragmentList.add(list3Fragment);
            fragmentList.add(list4Fragment);

第二种,解释起来比较麻烦,代码比较直观,直接上代码。

List<Fragment> saveFragmentList = getSupportFragmentManager().getFragments();
            if (saveFragmentList != null && saveFragmentList.size() > 0) {
                list1Fragment = (List1Fragment) saveFragmentList.get(0);
                list2Fragment = (List2Fragment) saveFragmentList.get(1);
                list3Fragment = (List3Fragment) saveFragmentList.get(2);
                list4Fragment = (List4Fragment) saveFragmentList.get(3);
            } else {
                list1Fragment = new List1Fragment();
                list2Fragment = new List2Fragment();
                list3Fragment = new List3Fragment();
                list4Fragment = new List4Fragment();
            }
            fragmentList.clear();
            fragmentList.add(list1Fragment);
            fragmentList.add(list2Fragment);
            fragmentList.add(list3Fragment);
            fragmentList.add(list4Fragment);

个人比较倾向于第二种。这两种方法的区别是,第一种会重新绘制所有相关的Fragment, 而第二种会保存Activity异常销毁前的Fragment的展示状态。

上一篇下一篇

猜你喜欢

热点阅读