更新基本导航抽屉活动的参数

Posted

技术标签:

【中文标题】更新基本导航抽屉活动的参数【英文标题】:Update an argument of a basic navigation drawer activity 【发布时间】:2021-02-16 15:35:41 【问题描述】:

上下文: 我想在他登录后将 userId 传递给片段 UserFragment。 我使用了一个新项目 android 类型“导航抽屉活动”。 我使用 LiveData,所以当用户登录时,我的 livedata 的观察者会从 MainActivity 更新 idUser。我还想更新导航组件中的片段参数...

val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
val navView: NavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
appBarConfiguration = AppBarConfiguration(setOf(
               R.id.nav_home, 
               R.id.userDetailItemNav, 
               R.id.dashboardItemNav), drawerLayout)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)

我的问题: 我只是想在导航时将 userId 的值作为目标(UserDetails 片段)的参数传递......但我不想创建一个 onClickListner 并在包中传递参数。我只想使用导航组件解决方案,因此只需更改导航组件中声明的片段的参数值 我在我的项目中添加了“Safe Args”。 我在其中一个目标片段上添加了一个“theUserId”参数:

在 mobile_navigation.xml 中:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/dashboardItemNav">
     <fragment (...)  />
     <fragment (...)  />
     <fragment
        android:id="@+id/userDetailItemNav"
        android:name="com.example.smart.ui.user.UserFragment"
        tools:layout="@layout/fragment_user" >
        <argument
            android:name="theUserId"
            app:argType="long"
            android:defaultValue="-1L"
            />
    </fragment>
</navigation>

在 UserFragment.kt 中:

// loading specifics arguments
val argument = arguments?.getLong("theUserId",999L)
Timber.i("userId from MainActivity: $argument")

我尝试了什么:

我在 MainActivity.kt 的 onCreate() 中的 LiveData 观察者是:

viewModel.user.observe(this, Observer  user ->
    if (user != null) 
       userId = user.id
       // TODO: here, change the value of my navigation argument theUserId
    

我尝试在我的 LiveData Observer 中添加一个 addOnDestinationChangedListner(但它会增加 Listner)。我还尝试直接在我的 MainActivity 的 OnCreate 中放置观察者(似乎更好):

navController.addOnDestinationChangedListener _, destination, arguments ->
    if (destination.id == R.id.userDetailItemNav) 
        userId?.let 
            val argument = NavArgument.Builder()
                      .setDefaultValue(it)
                      .build()
        
    

...但 userId 值仅在第二次单击后更新我的 UserDetail 片段的导航项。我不明白为什么。

我认为这段代码最好放在我的 Livedata 观察者中:

var userId = 75   // 75 is from my Livedata for example
var myArgs = UserFragmentArgs.Builder().setTheUserId(userId).build()

...但我不知道如何处理myArgs...如何使用它,如何将其注入到导航组件中,以便下次单击抽屉项“详细用户”时,我的论点“theUserId”在片段 UserFragment 中得到了很好的修改和检索。

感谢您的帮助。

【问题讨论】:

But I don't want to create an onClickListner and pass the argument in the bundle. 听起来您需要创建一个 onClickListener 并在 bundle 中传递参数。 【参考方案1】:

它不干净,但这是一个有效的解决方案。不幸的是,这个解决方案并没有完全尊重导航组件的精神......

在 MainActivity.kt 中,在 onCreate() 函数中:

viewModel.user.observe(this, Observer  user ->
    if (user != null) 
      userId = user.id
    


// (...)

navView.setNavigationItemSelectedListener  menuItem ->
    drawerLayout.closeDrawers()   // close drawer when item is tapped
    val bundle = bundleOf("theUserId" to userId)
    when (menuItem.itemId) 
        R.id.userDetailItemNav -> 
            navController.navigate(menuItem.itemId, bundle)
        
        else ->   // for other destination without parameter
          navController.navigate(menuItem.itemId)
        
    
    true

如果您有更好的想法(即能够直接在观察者中更改 UserId 参数的值),我很乐意采纳您的建议! .

【讨论】:

【参考方案2】:

我相信来自Documentation 的示例很容易适应您的用例。

【讨论】:

我已经阅读了这个文档,并在 *** 和 Google 上搜索了示例,但徒劳无功。我认为该文档解释了如何在经典事件上使用 SafeArgs(例如单击按钮,这很容易),但它没有解释如何仅更改导航图片段中定义的参数的值。该文档没有解释如何使用 SafeArgs 保持导航组件的工作精神。 ...或者我不明白,这就是为什么我请求你的帮助。

以上是关于更新基本导航抽屉活动的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何使用安全参数将数据从导航抽屉传递到活动?

在导航抽屉项目单击上启动新活动

导航抽屉开启新活动

所有活动中的Android导航抽屉[重复]

在导航抽屉上调用不是片段活动的活动

将导航抽屉活动扩展到其他活动