带参数的导航组件 .popBackStack()

Navigation Component .popBackStack() with arguments

我有两个片段。 SecondFragmentThirdFragment。实际上,我使用导航组件在片段之间传递值。像这样:

第二个片段:

val action = SecondFragmentDirections.action_secondFragment_to_thirdFragment().setValue(1)

Navigation.findNavController(it).navigate(action)

这是我从 ThirdFragment 中读取值的方式:

 arguments?.let {
           val args = ThirdFragmentArgs.fromBundle(it)
           thirdTextView.text = args.value.toString()
       }

工作正常。现在我的堆栈是这样的:

ThirdFragment

SecondFragment 

是否有任何选项可以使用新的导航组件将值从打开的ThirdFragment 传递到之前的SecondFragment? (当 ThirdFragment 完成时)

我知道 onActivityResult,但如果 Nav.Component 提供比我想要的更好的解决方案。

谢谢!

你要的是反模式。你应该

  • 使用您要设置的新值再次导航到第二个片段

  • 在单独的 activity 中使用第三个片段,并以 startActivityForResult()

  • 开头
  • 使用 ViewModel 或某种单例模式来保留您的数据(确保在不再需要数据后清除数据)

这些是我想到的一些模式。希望对你有帮助。

作为described here:

When navigating using an action, you can optionally pop additional destinations off of the back stack. For example, if your app has an initial login flow, once a user has logged in, you should pop all of the login-related destinations off of the back stack so that the Back button doesn't take users back into the login flow.

To pop destinations when navigating from one destination to another, add an app:popUpTo attribute to the associated element. app:popUpTo tells the Navigation library to pop some destinations off of the back stack as part of the call to navigate(). The attribute value is the ID of the most recent destination that should remain on the stack.

<fragment
    android:id="@+id/c"
    android:name="com.example.myapplication.C"
    android:label="fragment_c"
    tools:layout="@layout/fragment_c">

    <action
        android:id="@+id/action_c_to_a"
        app:destination="@id/a"
        app:popUpTo="@+id/a"
        app:popUpToInclusive="true"/>
</fragment>

这个答案有点晚了,但有人可能会觉得它有用。在导航组件库的更新版本中,现在可以在向后导航时传递数据。

假设栈是这样的

片段A --> 片段B.

我们现在在FragmentB,我们想在返回FragmentA时传递数据。

FragmentA里面我们可以用一个键创建一个观察者:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val navController = findNavController()
// Instead of String any types of data can be used
navController.currentBackStackEntry?.savedStateHandle?.getLiveData<String>("key")
    ?.observe(viewLifecycleOwner) { 

    }
}

然后在 FragmentB 中,如果我们通过访问先前的返回堆栈条目更改其值,它将传播到 FragmentA 并且观察者将收到通知。

val navController = findNavController()
navController.previousBackStackEntry?.savedStateHandle?.set("key", "value that needs to be passed")
navController.popBackStack()

刚接触到setFragmentResult(),很好用。关于此的文档是 here.

如果您正在导航:片段 A -> 片段 B -> 片段 A 将此添加到片段 A:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setFragmentResultListener("requestKey") { requestKey, bundle ->
        shouldUpdate = bundle.getBoolean("bundleKey")
    }
}

然后在片段B中添加这行代码:

setFragmentResult("requestKey", bundleOf("bundleKey" to "value to pass back"))
// navigate back toFragment A

当您导航回片段 A 时,侦听器将触发,您将能够获取包中的数据。