从FragmentB返回FragmentA后RecyclerView列表项不显示的问题
问题分析与解决方案
核心问题排查
返回FragmentA后RecyclerView为空,主要可能由以下几点导致:
- DiffUtil回调逻辑错误:
BondedDeviceDiffItemCallback中用hashCode判断内容是否一致,若未重写BondedDevice的hashCode方法,会直接比较对象内存地址,导致ListAdapter无法正确识别列表项内容,进而不更新UI。 - 广播接收器注册时机错误:当前在
onViewCreated注册、onDestroy注销接收器,Fragment被推入返回栈时不会触发onDestroy,导致重复注册接收器,可能干扰蓝牙设备状态获取。 - 生命周期收集时机问题:使用
repeatOnLifecycle(Lifecycle.State.RESUMED)收集数据流,回到FragmentA时虽会重新触发收集,但如果数据加载未及时完成,可能短暂显示空列表。
针对性解决方案
1. 修正DiffUtil回调逻辑
将BondedDeviceDiffItemCallback的areContentsTheSame方法改为直接比较对象属性(若BondedDevice是data class,可直接用==):
class BondedDeviceDiffItemCallback : DiffUtil.ItemCallback<BondedDevice>() { override fun areItemsTheSame(oldItem: BondedDevice, newItem: BondedDevice): Boolean { return oldItem.address == newItem.address } override fun areContentsTheSame(oldItem: BondedDevice, newItem: BondedDevice): Boolean { // 若BondedDevice是data class,直接用oldItem == newItem即可 return oldItem.name == newItem.name && oldItem.address == newItem.address } }
2. 调整广播接收器的注册/注销时机
将接收器的注册移至onStart,注销移至onStop,避免重复注册:
@AndroidEntryPoint class FragmentA : Fragment(R.layout.fragment_a) { // ... 其他代码 override fun onStart() { super.onStart() requireActivity().registerReceiver( bluetoothStateBroadcastReceiver, IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) ) } override fun onStop() { super.onStop() try { requireActivity().unregisterReceiver(bluetoothStateBroadcastReceiver) } catch (ignored: Exception) { } } // 删除原onDestroy中的注销代码 }
3. 确保返回时重新加载数据
在repeatOnLifecycle的RESUMED块中主动触发数据加载,保证回到FragmentA时数据最新:
lifecycleScope.launch { viewLifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.RESUMED) { // 每次进入前台时重新加载绑定设备 loadBondedDevices() viewModel.uiData.collect { uiData: UIData -> if (uiData.bondedDevices.isEmpty()) { viewBinding.emptyMtv.visibility = View.VISIBLE viewBinding.recyclerView.visibility = View.GONE } else { viewBinding.emptyMtv.visibility = View.GONE viewBinding.recyclerView.visibility = View.VISIBLE } bondedDevicesAdapter.submitList(uiData.bondedDevices) } } }
4. 确认UIData的初始化正确性
确保UIData的bondedDevices初始化为空列表,避免空指针或默认值异常:
data class UIData(val bondedDevices: List<BondedDevice> = emptyList())
额外建议
- 在
loadBondedDevices方法中添加日志,打印bluetoothAdapter.bondedDevices的大小,确认返回时是否能正确获取设备列表。 - 若
BondedDevice不是data class,建议重写equals和hashCode方法,保证对象比较逻辑的正确性。
内容的提问来源于stack exchange,提问作者dev.tejasb
相关产品推荐
相关产品推荐

