Android:使用 BottomNavigationView、NavController 和 SafeArgs 恢复片段

Android: Fragment restore with BottomNavigationView, NavController and SafeArgs

我目前正在开发 Android 应用程序,遇到了有关 BottomNavigationView 和 Fragment 的问题。我知道,有类似我的问题,但它们要么没有解决我的问题,要么没有有效的答案。

我的应用包含五个顶级目标片段。为了在它们之间导航,我使用 BottomNavigationView。此外,我有几个片段用作较低级别的目标,将从顶级片段之一调用。我使用 SafeArgs 插件导航到这些片段并将数据传递给。

我的 BottomNavigationView 配置如下所示:

val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = (supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment).navController

val appBarConfiguration = AppBarConfiguration(setOf(
    R.id.navigation_dest1, R.id.navigation_dest2, R.id.navigation_dest3,
    R.id.navigation_dest4, R.id.navigation_dest5))
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController);

这种用法的问题是 BottomNavigationView 似乎不支持将片段保存和存储在某处并重用这些实例进行导航。它只是创建一个新实例并显示它。

目前每个片段都包含一些数据获取代码,例如运行在协程中发出网络请求或从文件系统加载文件。而且因为 BottomNavigationView 不保留片段实例,所以这些数据获取部分 运行 太频繁了。
当然,我考虑过将数据获取过程放入主要 activity 但这会导致整体应用程序启动速度变慢,并且不能解决每次用户在它们之间导航时仍然需要重新创建片段的问题.

至此,我已经找到了一半的解决方案。通过使用 SupportFragmentManager,手动添加、显示和隐藏我的片段,它可以正常工作。但是应用程序 运行 的速度明显变慢,并且使用 SafeArgs 导航到我的较低级别的目的地不再有效。我使用 SafeArgs 是因为它易于使用且非常简单,我想继续使用它。

我尝试使用 SupportFragmentManager 手动管理它,但最终导致混乱和性能下降。

有什么已知的方法可以解决我的问题吗? BottomNavigationView 可以与 SafeArgs 和 SupportFragmentManager 交互以重用片段而不是在每个导航操作中重新创建片段?

(如果您需要更多信息或我的部分代码,请询问。我认为在这里发布我的完整代码没有多大意义。)

您是否考虑过与片段共享 ViewModel 的选项?例如:

像下面这样创建一个 ViewModel class:

 class MyViewModel: ViewModel() {
    ....
    ....
    }

然后,因为您的片段共享相同的 Activity,您可以声明以下内容(在 Kotlin 中):

 class MyFragment1: Fragment() {
        val viewModel: MyViewModel by activityViewModels()
        ....
        ....  
    }

    class MyFragment2: Fragment() {
        val viewModel: MyViewModel by activityViewModels()
        ....
        ....  

    }

在这种情况下,Fragment1 和 Fragment2 将共享同一个 ViewModel 实例,并且 ViewModel 将保留在内存中,直到 activity 被销毁。 导航出去时不会保留片段,但您可以保留每个片段的所有数据并重新使用它们。它快速而流畅,您不会介意是否重新创建片段,因为它的所有数据都将保存在内存中并准备好在共享 ViewModel 中使用。

另见官方文档: ViewModel Overview