Android-Jetpack

Navigation中Fragment重复创建问题

2020-10-24  本文已影响0人  徒步青云

在Navigation框架中,每次Fragment的navigate跳转,都是采用replace方法,这将导致相同Fragment跳转,会创建不同实例,导致界面数据重复加载,甚至丢失。源代码如下:FragmentNavigator.class

image.png

典型应用场景就是:Navigation配合BottomNavigationView作Home页面,当点击同一底部导航按钮,同一类型的Fragment会多次创建。然而,我们期望的是,如果目标页面跟当前页面一致,就不加载新的页面实例。这也是我们今天所要解决的问题。

这种解决办法有很多:

一、配合ViewModel使用

这种方式是Google所推崇的,它能保证Fragment被销毁后,数据依然有效,只要将数据展示在新的Fragment上,就能让用户觉得一切都未改变。
但这也带来了许多问题,如界面闪烁,列表当前位置丢失等等。

二、重写事件监听

仿造NavigationUI.setupWithNavController(bottomNavigationView, navController)方法,修改bottomNavigationView的setOnNavigationItemSelectedListener实现逻辑。让重复点击无效。
但这种方法“治标不治本”,如果通过NavController的navigate方法重复跳转,该问题依然存在。

3、修改FragmentNavigator

这种方式又分两种:

3.1、重写navigate方法

将replace修改成hide、show方法,实现过程较为复杂。这里就不详细展开了。

3.2、重写instantiateFragment方法

如果当前Fragment跟目标Fragment类型一致,就不创建新的实例,而是直接返回当前Fragment。

目前我们的解决方案正是采用本方法,实现过程如下:
1、主布局中去掉graphId,因为我们后续会手动添加

image.png

2、创建FixedFragmentNavigator类

@Navigator.Name("fragment")
public class FixedFragmentNavigator extends FragmentNavigator {
    private final int mContainerId;

    public FixedFragmentNavigator(@NonNull Context context, @NonNull FragmentManager manager, int containerId) {
        super(context, manager, containerId);
        mContainerId = containerId;
    }

    @NonNull
    @Override
    public Fragment instantiateFragment(@NonNull Context context, @NonNull FragmentManager fragmentManager, @NonNull String className, @Nullable Bundle args) {
        Fragment fragment = fragmentManager.findFragmentById(mContainerId);
        if (fragment != null) {
            String name = fragment.getClass().getName();
            if (className.equals(name)) {
                return fragment;
            }
        }
        return super.instantiateFragment(context, fragmentManager, className, args);
    }
}

3、将FixedFragmentNavigator替换掉默认的FragmentNavigator,再设置navGraph。

image.png

OK,完美解决。这里我只讲了最后一种方法,其余方法大家自行研究,毕竟我比较懒~~~~

上一篇 下一篇

猜你喜欢

热点阅读