setFragmentResult 不适用于 Click 侦听器

问题描述 投票:0回答:5

你好,我的问题如下,我有 2 个片段,一个使用 SetFragmentResultListener 接收,另一个使用 setFragmentResult 发送

问题是 setFragmentResult 不能在 OnClickListener 内部工作,但可以在外部工作

家长

 setFragmentResultListener("scannedCode") { requestKey, bundle ->
                val result = bundle.getString("code")
                Log.i("MYLOG-find","$result")
            }

孩子 - 它有效

override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_scan, container, false)

            setFragmentResult("scannedCode", bundleOf("code" to  "pedro"))
        
        return view
    }

孩子 - 这不起作用

 override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_scan, container, false)

        view.textView2.setOnClickListener {
            setFragmentResult("scannedCode", bundleOf("code" to  "pedro"))
        }

        return view
    }
android android-fragments retrofit dagger-2 fragmentmanager
5个回答
22
投票

根据 @ianhanniballake 的回答,我更进一步,因为我遇到了类似的问题,并阅读了他提到的文档(特别是在主机活动中接收结果部分)。进行片段间通信(父子)的关键之一是使用 Activity 的

supportFragmentManager
方法来执行信息交换。示例:

  • 父片段(主机)
requireActivity().supportFragmentManager
   .setFragmentResultListener("whatever_id_you_use", viewLifecycleOwner) {
   // Your code for listener
}
  • 子片段
requireActivity().supportFragmentManager
   .setFragmentResult("whatever_id_you_use", bundle_with_results)

"whatever_id_you_use"
是文档中描述的 requestKey,它是 Activity 在为其结果分配侦听器时将查找的索引。这样做应该使侦听器与生命周期保持同步,同时简化自己的侦听器的实现。


13
投票

在将数据从 Child 片段传递到 Parent 片段的情况下,在

parent 片段
上设置 resultListener 时,使用 childFragmentManager 是关键。

  • 父片段将代码放在里面
    onCreate()
    ):
childFragmentManager.setFragmentResultListener("requestKey", this ) { requestKey, bundle ->
            val resultReceived = bundle.getString("bundleKey")
            // do something with the result
            // ...  
        }
  • 子片段在需要发送结果时放置代码 - 可能来自点击侦听器,可能是当您从另一个启动的活动收到结果时,等等。):
 val resultToBeSent = "result"
 setFragmentResult("requestKey", bundleOf("bundleKey" to resultToBeSent))

有关片段之间通信的更多有用信息可以在这篇媒体文章中找到: 在片段之间传递数据的现代方式,当然还有 Android 官方文档:与片段通信


5
投票

当您使用导航组件时,当您导航到新片段时,前一个片段会停止。根据 Fragment Result API 指南

如果您对同一键多次调用

setFragmentResult()
,并且 如果侦听器不是
STARTED
,则系统会将所有待处理结果替换为您的更新结果。
如果您设置的结果没有相应的侦听器来接收它,结果存储在
FragmentManager
中,直到您使用相同的键设置侦听器。一旦侦听器收到结果并触发
onFragmentResult()
回调,结果就会被清除。这种行为有两个主要含义:

  1. 返回堆栈上的片段只有在被弹出并且
    STARTED
    时才会收到结果。
  2. 如果设置结果时侦听结果的片段是
    STARTED
    ,则会立即触发侦听器的回调。

因此,预计您不会收到对片段结果侦听器的任何调用,直到您弹回到该片段并且它再次变为

STARTED


0
投票

在我的例子中,将推送的片段结果发送到演示,我需要调用:

requireActivity().onBackPressed()
,然后
setFragmentResult()


0
投票

在父片段的

setFragmentResultListener
方法中调用
onViewCreated

因为根据

FragmentManager
的源码,当父fragment的
FragmentResultListener
被调用时,
onDestroyView
会被移除,所以当你回到父fragment时,你应该重新注册监听器以确保它被调用在父片段开始之后。

© www.soinside.com 2019 - 2024. All rights reserved.