本文介绍了Android:使用BottomNavigationView,NavController和SafeArgs还原片段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我当前正在使用Android应用,遇到有关BottomNavigationView和Fragments的问题.我知道,也有类似的问题,例如我的问题,或者它们不能解决我的问题,或者没有有效的答案.

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

我的BottomNavigationView配置如下:

  val navView:BottomNavigationView = findViewById(R.id.nav_view)val navController =(supportFragmentManager.findFragmentById(R.id.nav_host_fragment)as NavHostFragment).navControllerval 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不会保留片段实例,所以这些数据获取部分运行得太频繁.
当然,我曾考虑过将数据获取过程放入主要活动中,但这会导致应用程序启动总体上变慢,并且无法解决每次用户在它们之间导航时仍需要重新创建片段的问题.

到目前为止,我已经找到解决方案的一半.通过使用SupportFragmentManager,手动添加,显示和隐藏我的片段,它可以工作.但是该应用程序的运行速度明显变慢,并且使用SafeArgs导航到我的下级目的地不再起作用.我之所以使用SafeArgs,是因为它易于使用且非常轻松,我想继续使用它.

我尝试使用SupportFragmentManager手动管理所有操作,但最终导致混乱和性能下降.

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

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

解决方案

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

创建如下所示的ViewModel类:

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

然后,由于您的片段共享相同的活动,因此可以声明以下内容(在Kotlin中):

 类MyFragment1:Fragment(){val viewModel:由ActivityViewModels()创建的MyViewModel........}类MyFragment2:Fragment(){val viewModel:由ActivityViewModels()创建的MyViewModel........} 

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

另请参阅官方文档:

i'm currently working on an Android app and encountered a problem concerning BottomNavigationView and Fragments. I know, there are similar questions like mine but either they doesn't solve my problem or they have no working answers.

My app consists of five top-level destination fragments. For navigating between them I use the BottomNavigationView. Additionally, I have several fragments which serve as lower-level destinations and will be called from one of the top-level fragments. I use SafeArgs plugin to navigate to these fragments and also to pass data to.

My BottomNavigationView Configuration looks like this:

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);

The problem of this usage is that BottomNavigationView doesn't seem to provide support for saving and storing the fragments somewhere and reuse these instances for navigation. It just creates a new instance and displays it.

Currently each fragment contains some data fetching code, e.g. running a network request in a coroutine or loading files from the filesystem. And because BottomNavigationView doesn't preserve fragment instances, these data fetching parts are run too often.
Of course I thought about putting the data fetching process into the main activity but this results in an overall slower app-startup and doesn't solve the problem that the fragments still need to be recreated every time the user navigates between them.

Up to this point, I already found half of a solution. By using the SupportFragmentManager, manually adding, showing and hiding my fragments it works. But the app runs noticeably slower and the navigation to my lower-level destinations with SafeArgs just doesn't work anymore. I use SafeArgs because it's easy to use and pretty hassle-free, and I would like to keep using it.

I tried to manage it all manually with SupportFragmentManager, but it ends up in chaos and worse performance.

Is there any known way my problem can be solved? A way, BottomNavigationView can interact with SafeArgs and SupportFragmentManager to reuse the fragments instead of recreating them on each navigation action?

(If you need further information or parts of my code, please ask. I think posting my complete code here doesn't make much sense.)

Have you considered the option of sharing a ViewModel with your fragments ? For example:

Create a ViewModel class like the following:

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

Then, because your fragments share the same Activity, you can declare the following (in Kotlin):

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

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

    }

In this case Fragment1 and Fragment2 will share the same ViewModel instance and the ViewModel will remain in memory until the activity is destroyed.Fragments won't be preserved when you navigate out, but you can preserve all data of each fragment and re-use them. It is fast and smooth and you won't mind if the fragment is re-created because all its data will be kept in memory and ready for use in the shared ViewModel.

See also the official documentation:ViewModel Overview

这篇关于Android:使用BottomNavigationView,NavController和SafeArgs还原片段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 20:46
查看更多