如何使用Android导航组件将值传递回之前的片段目的地?

Ale*_*289 10 android android-fragments android-navigation android-jetpack android-architecture-navigation

让坐吧 我有一些这样的目的地

从片段 A --> 到片段 B --> 到片段 C

我可以使用 Safe Args 将数据从片段 A 传递到片段 B,也可以使用从片段 B 到片段 C 的安全参数。

如果我想将片段 C 中生成的字符串带回片段 B 或片段 A 怎么办?

要从片段 C 导航到片段 B,我使用代码:

Navigation.findNavController(fragmentView).navigateUp()
Run Code Online (Sandbox Code Playgroud)

并从片段 C 导航到片段 A,我使用代码:

Navigation.findNavController(view).popBackStack(R.id.fragmentA, false)
Run Code Online (Sandbox Code Playgroud)

那么如何将值传递回之前的片段目的地?我是否必须从片段 C 返回到片段 B 并通过安全参数传递值?

真的需要你的帮助。非常感谢 :)

Ami*_*mir 10

您可以使用以下代码段将数据发送到前一个片段。

观察数据的片段A:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")?.observe(viewLifecycleOwner) { data ->
        // Do something with the data.
    }
}
Run Code Online (Sandbox Code Playgroud)

发送数据的片段B:

findNavController().previousBackStackEntry?.savedStateHandle?.set("key", data)
findNavController().popBackStack()
Run Code Online (Sandbox Code Playgroud)

我还为此编写了扩展程序。

fun <T : Any> Fragment.setBackStackData(key: String,data : T, doBack : Boolean = true) {
    findNavController().previousBackStackEntry?.savedStateHandle?.set(key, data)
    if(doBack)
    findNavController().popBackStack()
}

fun <T : Any> Fragment.getBackStackData(key: String, result: (T) -> (Unit)) {
    findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<T>(key)?.observe(viewLifecycleOwner) {
        result(it)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

片段A:

getBackStackData<String>("key") { data ->
    // Do something with the data.
}
Run Code Online (Sandbox Code Playgroud)

片段B:

setBackStackData("key",data)

    
Run Code Online (Sandbox Code Playgroud)

注意:我使用 String 作为数据。您可以使用任何其他类型的变量。

注意:如果您打算使用 Class 作为数据,请不要忘记添加@Parcelizeannotation 和 extend Parcelable


or_*_*vir 0

我刚刚遇到了同样的问题,并且有几个我可以提出的选项(目前正在考虑哪个最适合我的用例)。

  1. 创建从片段 C 回到片段 A 的导航操作。请注意,如果这就是您所做的全部操作,您的堆栈现在将是:ABCA。为了避免这种情况,您可以使用popUpToPopUpToInclusive。请参阅文档

这种方法的缺点是片段A无论如何都会被清除,并且必须重新加载(并再次获取其所有数据)。

  1. ViewModel对片段使用共享,并使用 观察所需的值LiveData。在这种情况下,片段 C 将更新片段 A 观察到的LiveData共享中的值。ViewModel现在,当您返回片段 A 时,您observer将被片段 C 设置的值触发。

  2. 与选项 2 类似,如果您使用外部数据源(如Room数据库),您可以使用片段 A 来观察更改。LiveData在这种情况下,片段 C 所要做的就是更新数据源,片段 A 将通过以下方式自动更新这LiveData