横竖屏切换后DialogFragment无法向Fragment返回结果,求解决方案
解决DialogFragment横竖屏切换后Fragment结果回调失效问题
问题场景
使用setFragmentResult和setFragmentResultListener实现Fragment与DialogFragment的通信,正常功能可用,但DialogFragment经历横竖屏切换后,调用方Fragment的onFragmentResult方法不再被触发。
问题原因
横竖屏切换会触发Fragment和DialogFragment的销毁与重建:
- 原代码中调用方Fragment仅在打开Dialog时注册一次结果监听,重建后该监听未重新绑定;
- DialogFragment重建后,调用
setFragmentResult时,没有对应的活跃监听接收事件,导致回调失效。
解决方案
1. 调用方Fragment:在生命周期中重复注册监听
将setFragmentResultListener的注册逻辑移到onViewCreated方法中,该方法会在Fragment每次重建(包括横竖屏切换)时执行,确保监听始终处于活跃状态:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 每次Fragment重建都重新注册结果监听 setFragmentResultListener("roles") { requestKey, bundle -> onFragmentResult(requestKey, bundle) } } private fun getRoles() { val dialog = RoleDialog() dialog.show(parentFragmentManager.beginTransaction(), "roleDialog") } private fun onFragmentResult(requestKey: String, bundle: Bundle) { roles = bundle.getParcelableArrayList("roles", Role::class.java) }
2. DialogFragment:保存并恢复状态
横竖屏切换时,DialogFragment的临时数据(如选中的roles)会丢失,需在onSaveInstanceState中保存数据,重建时恢复:
class RoleDialog : DialogFragment() { private var roles: ArrayList<Role>? = null override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val inflater = requireActivity().layoutInflater val view = inflater.inflate(R.layout.dialog_role, null) val btnOk = view.findViewById<Button>(R.id.btnOk) // 从保存的状态中恢复数据 savedInstanceState?.let { roles = it.getParcelableArrayList("roles", Role::class.java) } btnOk.setOnClickListener { dismiss() setFragmentResult("roles", bundleOf("roles" to roles)) } return AlertDialog.Builder(requireContext()) .setView(view) .create() } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) // 保存当前选中的roles数据 outState.putParcelableArrayList("roles", roles) } }
注意事项
- 确保
Role类已经实现Parcelable接口,否则无法通过Bundle传递和恢复数据; - 避免使用
setRetainInstance(true),AndroidX Fragment已通过Saved State API原生支持状态保存,手动设置该属性可能引发视图重建异常。
内容的提问来源于stack exchange,提问作者Source
相关产品推荐
相关产品推荐

