【问题标题】:Pass data back to previous fragment using Android Navigation使用 Android Navigation 将数据传回上一个片段
【发布时间】:2019-05-21 16:57:14
【问题描述】:

我已经开始使用 Android 架构组件(导航和安全参数、视图模型)以及 Koin 库。

目前,我在两个片段之间传递参数时遇到问题 - 我需要将字符串值从片段 A 传递给片段 B,在片段 B 中修改此值并将其传递回片段 A。

我找到了一种可能的解决方案 - 共享视图模型。不幸的是,这种方法有一个问题,因为我可以在屏幕之间传递和修改值,但是当片段 A 导航到另一个目的地时,共享视图模型中的值仍然被存储而不是清除。

在 Android Navigation 的 Fragment 之间传递和修改数据有什么不同的解决方案吗?我想避免手动清除这个值(当片段 A 被销毁时)。

【问题讨论】:

标签: android android-jetpack android-navigation android-architecture-navigation koin


【解决方案1】:

Android 刚刚发布了一个解决方案; Passing data between Destinations (Navigation 2.3.0-alpha02),基本上,在片段 A 中,您观察变量的变化,在片段 B 中,您在执行 popBackStack() 之前更改该值。

片段 A:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val navController = findNavController();
// We use a String here, but any type that can be put in a Bundle is supported
navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(
    viewLifecycleOwner) { result ->
    // Do something with the result.
  }
}

片段 B:

navController.previousBackStackEntry?.savedStateHandle?.set("key", result)
navController.popBackStack()

【讨论】:

  • 谢谢!它有效,但与将数据从 Fragment A 传递到 Fragment B 时相比,这是一个非常奇怪的解决方案。这种解决方案更像是我们过去在 Java 中使用 bundle 传递数据的旧方法。
  • 我们可以使用这个传递多个数据吗?
  • 干得好!!!坚持下去
  • 注意:Hilt 注入 ViewModel 的 SavedStateHandle 和 NavBackStackEntry SavedStateHandle 不是同一个对象。我花了几个小时弄清楚这个
  • 我需要一种在 Viewmodel 中设置 onBackPressed 事件的方法。我搜索了很多很多小时。就是这样。
【解决方案2】:

目前,我在两个片段之间传递参数时遇到问题 - 我需要将字符串值从片段 A 传递到片段 B,在片段 B 中修改此值并将其传递回片段 A。

理论上的解决方案实际上是将两个片段放在一个共享的&lt;navigation 标签中,然后将 ViewModel 限定为导航标签的 ID,这样您现在就可以在两个屏幕之间共享 ViewModel。

为了使其可靠,最好将 Navigation 标记的 NavBackStackEntry 用作 ViewModelStoreOwner 和 SavedStateRegistryOwner,并创建一个 AbstractSavedStateViewModelFactory,它将使用 ViewModelProvider 创建 ViewModel,同时还为您提供 SavedStateHandle。

您可以使用此 SavedStateHandle 将结果从 FragmentB 传达给 FragmentA,与共享 ViewModel 相关联(范围为共享 NavGraph)。

【讨论】:

    【解决方案3】:

    你可以试试这个解决方案

    <fragment
        android:id="@+id/a"
        android:name="...">
    
        <argument
            android:name="text"
            app:argType="string" />
    
        <action
            android:id="@+id/navigate_to_b"
            app:destination="@id/b" />
    
    </fragment>
    
    <fragment
        android:id="@+id/b"
        android:name="...">
    
        <argument
            android:name="text"
            app:argType="string" />
    
        <action
            android:id="@+id/return_to_a_with_arguments"
            app:destination="@id/a"
            app:launchSingleTop="true"
            app:popUpTo="@id/b"
            app:popUpToInclusive="true" />
    
    </fragment>
    
    

    和导航片段

    NavHostFragment.findNavController(this).navigate(BFragmentDirections.returnToAWithArguments(text))
    

    ianhanniballake 的 comment 帮助我解决了类似的问题

    【讨论】:

      【解决方案4】:

      您可以使用Fragment Result API

      片段 A -> 片段 B

      在片段 A 中:

      binding.buttonGo.setOnClickListener {
         setFragmentResultListener(ADD_LOCATION) { key, bundle ->
             clearFragmentResultListener(requestKey = ADD_LOCATION)
             val selectedLocationModel =
                 bundle.getParcelable<LocationModel>(SELECTED_LOCATION_MODEL)
             this.selectedLocationModel = selectedLocationModel
         }
         navToFragmentB()
      }
      

      在片段 B 中:

      setFragmentResult(
          ADD_LOCATION,
          bundleOf(SELECTED_LOCATION_MODEL to selectedLocationModel)
      )
      goBack()
      

      在创建新的之前不要忘记致电clearFragmentResultListener()

      【讨论】:

        【解决方案5】:

        1) 使用 action_A_to_B 和 SafeArgs 将字符串从 Fragment A 传递到 Fragment B。

        2) popBackStack 移除 Fragment B。

        navController.popBackStack(R.id.AFragment, false);
        

        navController.popBackStack();
        

        3) 然后使用 action_B_to_A 将修改后的数据从 B 传递到 A。

        编辑。

        给你另一个solution

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-01-14
          • 2017-07-31
          • 1970-01-01
          • 2013-10-20
          • 2013-01-29
          • 2021-04-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多