Bottom Sheet Dialog Fragment无法获取Fragment Result API值的问题
问题排查与解决方案
核心原因:结果发送时机早于监听器注册
Fragment Result API的工作逻辑是先注册监听器,再发送结果——如果结果已经发送完毕,后续注册的监听器无法回溯接收之前的结果。你当前的执行流程是:
- 先调用
parentFragmentManager.setFragmentResult()发送数据 - 再启动BottomSheet Fragment,它在
onCreateView中才注册监听器
这就导致监听器注册时,结果已经发送过,自然接收不到数据。
排查与修复步骤
1. 调整调用顺序,确保监听器先注册再发送结果
修改主Fragment逻辑,先启动BottomSheet,再发送结果:
// 主Fragment中 val bottomSheet = InfoBottomSheetFragment.newInstance() bottomSheet.show(parentFragmentManager, InfoBottomSheetFragment.TAG) // 发送结果 parentFragmentManager.setFragmentResult( WEATHER_RESPONSE_KEY, bundleOf(WEATHER_RESPONSE_KEY to newValue) )
更可靠的方式是给BottomSheet添加初始化回调,确保监听器注册完成后再发送数据:
// InfoBottomSheetFragment中定义回调接口 interface OnSheetReadyListener { fun onSheetReady() } // 主Fragment实现接口 class MainFragment : Fragment(), InfoBottomSheetFragment.OnSheetReadyListener { override fun onSheetReady() { parentFragmentManager.setFragmentResult( WEATHER_RESPONSE_KEY, bundleOf(WEATHER_RESPONSE_KEY to newValue) ) } // 启动BottomSheet时绑定回调 fun showBottomSheet() { val bottomSheet = InfoBottomSheetFragment.newInstance().apply { readyListener = this@MainFragment } bottomSheet.show(parentFragmentManager, InfoBottomSheetFragment.TAG) } } // BottomSheet的onCreateView中触发回调 override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { // 先注册监听器 parentFragmentManager.setFragmentResultListener(WeatherFragment.WEATHER_RESPONSE_KEY, viewLifecycleOwner){_,bundle-> weatherResponse = bundle.getSerializable(WeatherFragment.WEATHER_RESPONSE_KEY) as WeatherResponse } // 再通知主Fragment发送数据 readyListener?.onSheetReady() return inflater.inflate(R.layout.bottom_sheet_info, container, false) }
2. 验证Key的一致性
确认WEATHER_RESPONSE_KEY在两个Fragment中是同一个常量,避免拼写错误或独立定义导致的不一致:
// 统一在全局类中定义常量 object FragmentConstants { const val WEATHER_RESPONSE_KEY = "weather_response_key" }
两边都使用FragmentConstants.WEATHER_RESPONSE_KEY调用相关API。
3. 确认WeatherResponse正确实现序列化接口
如果使用getSerializable(),必须确保WeatherResponse类正确实现Serializable接口:
data class WeatherResponse(/* 字段定义 */) : Serializable
若使用Parcelable,则需替换为bundle.getParcelable<WeatherResponse>(KEY)。
4. 改用ViewModel共享数据(更推荐的跨Fragment通信方式)
对于同属一个Activity的Fragment,使用ViewModel共享数据可以彻底规避时序问题:
// 定义共享ViewModel class WeatherSharedViewModel : ViewModel() { val weatherResponse = MutableLiveData<WeatherResponse>() } // 主Fragment中更新数据 val sharedViewModel = ViewModelProvider(requireActivity())[WeatherSharedViewModel::class.java] sharedViewModel.weatherResponse.value = newValue // BottomSheet Fragment中观察数据 val sharedViewModel = ViewModelProvider(requireActivity())[WeatherSharedViewModel::class.java] sharedViewModel.weatherResponse.observe(viewLifecycleOwner) { response -> weatherResponse = response }
内容的提问来源于stack exchange,提问作者dobriy denyok
相关产品推荐
相关产品推荐

