Android BottomSheetDialogFragment间数据传递问题:B向A传值失败求助
BottomSheetDialogFragment 数据传递:B向A回传数据的实现方案
调用逻辑序列
- 调用A(AddScheduleBottomSheetDialogFragment)
- 在A中调用B(SearchLocationDialog)
- 需要将B中选择的地址数据传递给A,尝试过在B中用LiveData、A中观察,但未成功
- 询问如何用LiveData或Fragment Bundle/Arguments方案实现B到A的数据传递
相关代码
调用A的代码
private fun initAddSchedulebutton(){ binding.btnFragmentCalendarAddSchedule.setOnClickListener { AddScheduleBottomSheetDialogFragment().also { it.show( requireActivity().supportFragmentManager, it.tag, ) } } }
A中调用B的代码
private fun initSearchLocationButton() { binding.tvDialogCreateScheduleSearchLocation.setOnClickListener { SearchLocationDialog().also { it.show( requireActivity().supportFragmentManager, it.tag, ) } } }
B中选择地址后的处理代码
private fun initSelectButton(){ binding.tvDialogSearchLocationSelectLocation.setOnClickListener { dismiss() } }
问题分析
调用B时,A已经处于onViewCreated生命周期,无法通过arguments传递数据;且B销毁时其ViewModel也会被销毁,导致A无法观察到B的LiveData变化。
解决方案
方案一:共享ViewModel(LiveData方案)
核心是让A和B绑定到Activity级别的同一个ViewModel实例,避免B销毁后ViewModel被回收,保证A能持续观察数据。
- 定义共享ViewModel
class SharedLocationViewModel : ViewModel() { val selectedLocation = MutableLiveData<String>() // 根据实际数据类型调整 }
- A中获取ViewModel并监听数据
在A的onViewCreated方法中:
private val sharedViewModel by activityViewModels<SharedLocationViewModel>() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 监听选中的地址数据 sharedViewModel.selectedLocation.observe(viewLifecycleOwner) { location -> // 拿到数据后更新A的UI或执行后续逻辑 binding.tvDialogCreateScheduleSearchLocation.text = location } }
- B中获取ViewModel并设置数据
修改B的选择按钮点击事件:
private val sharedViewModel by activityViewModels<SharedLocationViewModel>() private fun initSelectButton(){ binding.tvDialogSearchLocationSelectLocation.setOnClickListener { // 替换为实际获取的选中地址数据 val selectedAddr = "用户选中的地址内容" sharedViewModel.selectedLocation.value = selectedAddr dismiss() } }
方案二:Fragment Result API(Bundle衍生官方方案)
这是Jetpack提供的Fragment间数据传递标准方案,适配弹窗Fragment回传数据的场景。
- A中注册结果监听
在A的onViewCreated中注册,使用唯一请求Key:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 注册结果监听,KEY_LOCATION_REQUEST为自定义唯一标识 parentFragmentManager.setFragmentResultListener(KEY_LOCATION_REQUEST, viewLifecycleOwner) { _, bundle -> val location = bundle.getString(KEY_LOCATION_DATA) location?.let { // 处理回传的地址数据 binding.tvDialogCreateScheduleSearchLocation.text = it } } } // 定义常量,可放在A类内部或单独常量类中 companion object { private const val KEY_LOCATION_REQUEST = "location_request" private const val KEY_LOCATION_DATA = "location_data" }
- B中设置回传结果
修改B的选择按钮点击事件:
private fun initSelectButton(){ binding.tvDialogSearchLocationSelectLocation.setOnClickListener { // 替换为实际获取的选中地址数据 val selectedAddr = "用户选中的地址内容" // 封装数据到Bundle val resultBundle = Bundle().apply { putString(KEY_LOCATION_DATA, selectedAddr) } // 传递结果,请求Key需与A中一致 parentFragmentManager.setFragmentResult(KEY_LOCATION_REQUEST, resultBundle) dismiss() } } // 定义对应常量,或直接引用A中的常量 companion object { private const val KEY_LOCATION_REQUEST = "location_request" private const val KEY_LOCATION_DATA = "location_data" }
内容的提问来源于stack exchange,提问作者Tmdhoon2
相关产品推荐
相关产品推荐

