片段生命周期重叠导航

roz*_*ina 8 android fragment-lifecycle android-architecture-components android-jetpack android-architecture-navigation

我有一个使用导航组件切换的Activity多个应用程序Fragments.当我在两个片段之间切换时,它们onCreate()onDestroy()方法似乎重叠.因此,当我们访问相同的全局对象时,我很难为片段编写初始化和清理代码.

导航Framgent_AFragment_B具有以下方法顺序:

Fragment_B.onCreate()
Fragment_A.onDestroy()
Run Code Online (Sandbox Code Playgroud)

Fragment_A.onDestroy()我逆转我做的操作Fragment_A.onCreate().而且Fragment_B我希望事情在onCreate()被召唤时处于中立状态.然而事实并非如此,因为Fragment_A.onDestroy()尚未召集.

Android上的重叠是否正常,或者我的导航组件中是否配置了错误?还有另一种方法可以实现我想做的事情吗?我知道我可以将两者结合起来Fragments并使其发挥作用,但我不想让Fragment彼此了解.对我而言,Framgnet_AFragment_B创建时,仍然存在时似乎很奇怪,何时Fragment_B应该替换Fragment_A.

任何帮助是极大的赞赏!


编辑:

在调试源代码之后,我发现在FragmentNavigator.navigate() FragmentTransaction.setReorderingAllowed()中调用了它,它允许重新排序操作,甚至允许在前一个之前onCreate()调用一个新的片段onDestroy().问题仍然存在,如何在下一个片段中初始化相同的全局状态之前解决我在一个片段中正确清理全局状态的问题.

tyn*_*ynn 8

Android的 Fragment生命周期是不是真的适合您的需要适当的回调主机。导航控制器将用动画替换两个片段,因此两者都以某种方式同时可见,最终甚至在进入onPause()片段之后调用退出片段onResume()

解决方案 1:使用 OnDestinationChangedListener

onDestinationChanged()回调之前,任何的生命周期事件的调用。作为一种非常简化的方法(注意泄漏),您可以执行以下操作:

    findNavController().addOnDestinationChangedListener { _, destination, _ ->
        if(shouldCleanupFor(destination)) cleanup()
    }
Run Code Online (Sandbox Code Playgroud)

解决方案 2:抽象全局变化

与其让单个导航点改变全局状态,不如让单个导航点改变全局状态。这可能是另一个独立于导航层次结构的片段。然后像以前一样观察导航:

findNavController(R.id.nav_graph).addOnDestinationChangedListener { _, destination, _ ->
    resetAll()
    when(distination.id) {
        R.id.fragment_a -> prepareForA()
        R.id.fragment_b -> prepareForB()
        else -> prepareDefault()
    }
}
Run Code Online (Sandbox Code Playgroud)

作为额外的优势,您也可以幂等地实现状态更改。

  • 无论好坏,导航库更改了导航期间片段的默认行为,因此您需要使用上面的解决方法或不使用导航库 - https://issuetracker.google.com/issues/155574963 (2认同)

skr*_*ych 2

由于您有一个控制片段膨胀的活动,您可以手动控制正在膨胀的片段的生命周期。通过调用以下方法,您可以控制哪个片段准备好使用全局数据。此时,您必须了解如何将数据传递回 Mainactivity 以确定哪个片段处于活动状态,因为您询问如何同时膨胀 2 个片段以共享一个对象。更好的方法是让 MainActivity 实现 FragmentA 和 FragmentB-detail 并使用特定的类来执行操作,这样您就必须像平板电脑一样对待您的应用程序并确定 2 窗格模式,以及您可以使用由您控制的那些片段中的适当类。活动。包含的链接与您想要实现的目标相匹配

private void addCenterFragments(Fragment fragment) {
        try {
            removeActiveCenterFragments();
            fragmentTransaction = fragmentManager.beginTransaction();
            fragmentTransaction.add(R.id.content_fragment, fragment);
            fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            activeCenterFragments.add(fragment);
            fragmentTransaction.commit();
        }catch (Exception e){
            Crashlytics.logException(e);
        }
    }

    private void removeActiveCenterFragments() {
        if (activeCenterFragments.size() > 0) {
            fragmentTransaction = fragmentManager.beginTransaction();
            for (Fragment activeFragment : activeCenterFragments) {
                fragmentTransaction.remove(activeFragment);
            }
            activeCenterFragments.clear();
            fragmentTransaction.commit();
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 我正在使用新的导航组件,它为我执行片段事务。否则是一个有效的方法。 (2认同)