Android RecyclerView绑定Firebase数据不显示,需notifyDataSetChanged的原因咨询
Firebase数据加载与RecyclerView更新的疑问解答
我的App功能是从Firebase获取数据并在RecyclerView中展示,遇到了一个执行顺序相关的疑问,以下是我的代码:
val productList = mutableListOf<Product>() database.get().addOnSuccessListener { for (item in it.children) { productList.add(Product( item.key.toString(), item.child("name").value.toString(), item.child("photo").value.toString(), item.child("content").value.toString(), decimal.format(item.child("price").value.toString().toInt()).toString() + " P", item.child("price").value.toString().toInt() )) } binding.pointMallHomeRecyclerView.adapter?.notifyDataSetChanged() // 这里是我疑惑的点 } val myDataset = productList val adapter = PointMallMainItemAdapter(requireContext(), myDataset, object: PointMallMainItemAdapter.OnItemClickListener { override fun onItemClick(v: View, position: Int, id: String, content: String, photo: String) { val action = PointMallHomeFragmentDirections.actionPointMallHomeFragmentToPointMallItemFragment(productId = id, content = content, photo = photo) findNavController().navigate(action) } }) binding.pointMallHomeRecyclerView.adapter = adapter
最初没加notifyDataSetChanged()时,明明productList里已经有数据了,但RecyclerView就是没内容;加上之后就正常了。我疑惑:代码不是按顺序执行吗?是不是适配器绑定比数据库取数据更快?按顺序的话应该先取完数据再绑定适配器才对?
核心原因是Firebase的get()是异步操作,代码不是严格按你写的从上到下同步执行的,具体流程是:
- 你创建空的
productList后调用database.get()——这个方法不会卡住主线程等待服务器返回数据,而是立即返回,主线程继续执行后面的代码:创建适配器、把适配器绑定到RecyclerView。这时候productList还是空的,适配器拿到的是空数据集,RecyclerView自然显示为空。 - 等Firebase服务器返回数据后,
addOnSuccessListener里的代码才会在主线程执行,把数据添加到productList里。但这时候适配器已经绑定完成,它并不知道数据源已经更新,所以必须手动调用notifyDataSetChanged(),告诉适配器:数据源变了,重新加载数据并刷新列表。
简单说就是:绑定适配器的代码比Firebase返回数据的代码先执行,所以必须手动通知适配器更新。
优化建议
- 如果你不想手动调用
notifyDataSetChanged(),可以用LiveData包装productList,让适配器观察LiveData的变化,自动刷新列表,这更符合Android架构规范。 - 也可以把适配器的创建和绑定逻辑放到
addOnSuccessListener里,但这样每次数据更新都要重新创建适配器,不如用同一个适配器+通知更新高效。
内容的提问来源于stack exchange,提问作者hard0232
相关产品推荐
相关产品推荐

