setFragmentResult 不适用于 Click 侦听器

Seb*_*die 14 android android-fragments retrofit fragmentmanager dagger-2

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

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

家长

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

儿童 - 它有效

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
    }
Run Code Online (Sandbox Code Playgroud)

孩子——这不起作用

 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
    }
Run Code Online (Sandbox Code Playgroud)

Fra*_*ede 20

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

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

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


小智 13

在将数据从 Child 片段传递到 Parent 片段的情况下,在父片段childFragmentManager上设置 resultListener 时使用 是关键。

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

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


ian*_*ake 5

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

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

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

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