34

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

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

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

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

4

4 回答 4

51

Android 刚刚为此发布了解决方案;在 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()
于 2020-04-15T21:34:58.497 回答
1

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

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

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

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

于 2020-06-10T15:01:04.217 回答
0

你可以试试这个解决方案

<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 的评论帮助我解决了类似的问题

于 2020-06-10T14:55:48.060 回答
-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。

编辑。

在这里你有一些其他的解决方案

于 2019-05-23T20:58:07.467 回答