当前位置: 首页 > 知识库问答 >
问题:

如何使用导航架构组件从片段中获得结果?

郁承运
2023-03-14

假设我们有两个片段:MainFragment和SelectionFragment。第二个是用于选择某些对象的构建,例如整数。从第二个片段接收结果有不同的方法,如回调、总线等。

现在,如果我们决定使用导航架构组件来导航到第二个片段,我们可以使用以下代码:

NavHostFragment.findNavController(this).navigate(R.id.action_selection, bundle)

其中,bundle是bundle的一个实例(当然)。正如您所见,我们无法访问SelectionFragment,在那里我们可以放置回调。问题是,如何使用导航架构组件接收结果?


共有3个答案

荆煌
2023-03-14

使用这些扩展功能

fun <T> Fragment.getNavigationResult(key: String = "result") =
    findNavController().currentBackStackEntry?.savedStateHandle?.get<T>(key)

fun <T> Fragment.getNavigationResultLiveData(key: String = "result") =
        findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<T>(key)

fun <T> Fragment.setNavigationResult(result: T, key: String = "result") {
    findNavController().previousBackStackEntry?.savedStateHandle?.set(key, result)
}

所以如果你想把结果从片段B发送到片段A

内部碎片B

setNavigationResult(false, "someKey")

内部碎片A

val result = fragment.getNavigationResultLiveData<Boolean>("someKey")
result.observe(viewLifecycleOwner){ booleanValue-> doSomething(booleanValue)

重要说明

在片段B中,您需要将结果(setNavigationResult())设置为开始或恢复状态(在onStop()或onDestroy()之前),否则previousBackStackEntry将已经为空。

重要提示#2

如果只希望只处理一次结果,则必须对SavedStateHandle调用remove()以清除结果。如果不删除结果,LiveData将继续将最后一个结果返回给任何新的观察者实例。

更多信息请参阅官方指南。

闽涵蓄
2023-03-14

由于Fragment KTX 1.3.6,Android支持在片段之间或片段与活动之间传递数据。它类似于startActivityForResult逻辑

下面是一个导航组件的示例。你可以在这里了解更多

build.gradle

implementation "androidx.fragment:fragment-ktx:1.3.6"

碎片a。千吨

class FragmentA : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        // Step 1. Listen for fragment results
        setFragmentResultListener(FragmentB.REQUEST_KEY) { key, bundle -> 
            // read from the bundle
        }

        // Step 2. Navigate to Fragment B
        findNavController().navigate(R.id.fragmentB)
    }
}

碎片B。千吨

class FragmentB : Fragment() {

    companion object {
        val REQUEST_KEY = "FragmentB_REQUEST_KEY"
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

        buttonA.setOnClickListener { view -> 
            // Step 3. Set a result
            setFragmentResult(REQUEST_KEY, bundleOf("data" to "button clicked"))
            
            // Step 4. Go back to Fragment A
            findNavController().navigateUp()
        }
    }
}    
芮承运
2023-03-14

他们在2.3.0-alpha02版本中对此进行了修复。

如果从片段A导航到片段B并且A需要来自B的结果:

findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Type>("key")?.observe(viewLifecycleOwner) {result ->
    // Do something with the result.
}

如果在片段B上,需要设置结果:

findNavController().previousBackStackEntry?.savedStateHandle?.set("key", result)

我最终为此创建了两个扩展:

fun Fragment.getNavigationResult(key: String = "result") =
    findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>(key)

fun Fragment.setNavigationResult(result: String, key: String = "result") {
    findNavController().previousBackStackEntry?.savedStateHandle?.set(key, result)
}
 类似资料:
  • 我正在我的应用程序中尝试导航架构组件。早些时候,我使用片段事务来实现以下功能。基本上,我想从导航。 碎片- 如果我正在使用导航组件并尝试 然后结果是FragmentA被FragmentB替换并且背景片段不可见。 我想知道一个解决方案,如果导航架构组件允许的话。 附言:我听说过嵌套导航主机,但从内部使用它好吗。 更新: FragmentB将有进一步交易的行动,例如: 碎片- 当用户按下后退按钮时,片

  • 我正在使用BottomSheetDialogFraenge显示几个自定义设置的。 要求: 当我点击任何选项卡在BottomSheetDialogFraance我替换的片段,并将其添加到backstack,以便当用户点击的onBackPress或向上的行动,它应该回到最后设置的BottomSheetDialogFraank的片段。 我想使用导航架构组件来简化我的事务。 问题:如果我使用导航架构组件从

  • null 在调用之前和之后,我尝试了,但都不起作用(这是有意义的:在它没有要弹出的内容之前;在它只关闭刚刚添加的片段之后)。这是否意味着唯一的方法是重写来拦截它,并确保在这些情况下不会被调用? 谢了!

  • 是否可以将新的导航架构组件与DialogFragment一起使用?我必须创建自定义导航器吗? 我很乐意将它们与导航图中的新功能结合使用。

  • 在尝试导航组件之前,我曾手动执行片段事务,并使用片段标记获取当前片段。 现在在我的主要活动布局中,我有这样的东西: 如何通过导航组件检索当前显示的片段?做 返回一个,我想检索我显示的'MyFraank'。 非常感谢。

  • 我正在使用Android的导航架构组件。 对于我的一个片段,我希望拦截“后退”和“向上”导航,以便在放弃用户未保存的任何更改之前显示一个确认对话框。(编辑事件详细信息后按back/up时的行为与默认日历应用程序相同) 我目前的方法(未经测试)如下: 对于“向上”导航,我覆盖片段上的选项ItemSelected: 为了“返回”导航,我在片段及其活动之间创建了一个自定义接口和回调系统: 对于这样一件简