Firebase数据更新后Android RecyclerView不刷新,如何修复?
问题:RecyclerView无法刷新显示Firebase获取的数据
在Kotlin开发的Android应用中,尝试通过RecyclerView展示Firebase数据库中的数据,onDataChange函数已触发且数据获取正常,但RecyclerView始终无法刷新显示更新内容。
相关代码片段
Fragment中RecyclerView初始化与数据获取代码
class CategoryFragment : Fragment() { private lateinit var databaseReference: DatabaseReference private lateinit var categoryAdapter: CategoryAdapter override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val view = inflater.inflate(R.layout.fragment_category, container, false) // 初始化categoryAdapter categoryAdapter = CategoryAdapter(emptyList()) // 设置RecyclerView属性 val recyclerView: RecyclerView = view.findViewById(R.id.recyclerViewCategories) recyclerView.layoutManager = LinearLayoutManager(requireContext(), RecyclerView.VERTICAL, false) recyclerView.setHasFixedSize(true) recyclerView.adapter = categoryAdapter Log.d("CategoryFragment", "onCreateView is called") return view } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) Log.d("CategoryFragment", "onViewCreated is called") databaseReference = FirebaseDatabase.getInstance("https://foxycodecasestudy-default-rtdb.europe-west1.firebasedatabase.app").getReference("categories") Log.d("CategoryFragment", "Database reference: $databaseReference") // Debug日志 Log.d("CategoryFragment", "onViewCreated is called") databaseReference.addValueEventListener(object : ValueEventListener { override fun onDataChange(dataSnapshot: DataSnapshot) { val categories = mutableListOf<CategoryModel>() // Debug日志 Log.d("CategoryFragment", "onDataChange is called") for (categorySnapshot in dataSnapshot.children) { val enName = categorySnapshot.child("en").getValue(String::class.java) val trName = categorySnapshot.child("tr").getValue(String::class.java) Log.d("CategoryFragment", "enName: $enName, trName: $trName") if (enName != null && trName != null) { val category = CategoryModel(enName, trName) categories.add(category) } } categoryAdapter.setCategories(categories) categoryAdapter.notifyDataSetChanged() Log.d("CategoryFragment", "RecyclerView updated. Item count: ${categoryAdapter.itemCount}") } override fun onCancelled(databaseError: DatabaseError) { val errorMessage = databaseError.message Log.e("CategoryFragment", "FirebaseError: $errorMessage") } }) } }
CategoryAdapter代码
class CategoryAdapter(private var categories: List<CategoryModel>) : RecyclerView.Adapter<CategoryAdapter.ViewHolder>() { fun setCategories(categories: List<CategoryModel>) { this.categories = categories notifyDataSetChanged() Log.d("CategoryAdapter", "Categories updated. Count: ${categories.size}") Log.d("CategoryAdapter", "First category: ${categories.firstOrNull()?.en}") } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_cardview, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val category = categories[position] holder.bind(category) } override fun getItemCount(): Int { return categories.size } class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private val textViewTrName: TextView = itemView.findViewById(R.id.textViewCategoryEn) private val textViewEnName: TextView = itemView.findViewById(R.id.textViewCategoryTr) fun bind(category: CategoryModel) { textViewTrName.text = category.tr textViewEnName.text = category.en } } }
日志输出
onCreateView is called
...
onDataChange is called
enName: Family, trName: Aile
enName: Nature, trName: Doğa
...
Categories updated. Count: 10
First category: Family
RecyclerView updated. Item count: 10
修复方案
核心问题定位
- ViewHolder中TextView绑定逻辑错误:
ViewHolder里将textViewTrName绑定到了R.id.textViewCategoryEn,textViewEnName绑定到了R.id.textViewCategoryTr,同时在bind方法中又把category.tr赋值给textViewTrName、category.en赋值给textViewEnName,导致数据与UI控件的对应关系混乱,即使数据更新也无法正确显示。 - 重复调用
notifyDataSetChanged():
Fragment的onDataChange中调用了一次notifyDataSetChanged(),而Adapter的setCategories方法里已经调用了一次,属于冗余操作。
修正后的代码
修正后的CategoryAdapter
class CategoryAdapter(private var categories: List<CategoryModel>) : RecyclerView.Adapter<CategoryAdapter.ViewHolder>() { fun setCategories(categories: List<CategoryModel>) { this.categories = categories notifyDataSetChanged() Log.d("CategoryAdapter", "Categories updated. Count: ${categories.size}") Log.d("CategoryAdapter", "First category: ${categories.firstOrNull()?.en}") } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_cardview, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { val category = categories[position] holder.bind(category) } override fun getItemCount(): Int { return categories.size } class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { // 修正:TextView变量名与布局ID对应 private val textViewEnName: TextView = itemView.findViewById(R.id.textViewCategoryEn) private val textViewTrName: TextView = itemView.findViewById(R.id.textViewCategoryTr) fun bind(category: CategoryModel) { textViewEnName.text = category.en textViewTrName.text = category.tr } } }
修正后的Fragment数据更新逻辑
// ... 其他代码保持不变 override fun onDataChange(dataSnapshot: DataSnapshot) { val categories = mutableListOf<CategoryModel>() Log.d("CategoryFragment", "onDataChange is called") for (categorySnapshot in dataSnapshot.children) { val enName = categorySnapshot.child("en").getValue(String::class.java) val trName = categorySnapshot.child("tr").getValue(String::class.java) Log.d("CategoryFragment", "enName: $enName, trName: $trName") if (enName != null && trName != null) { val category = CategoryModel(enName, trName) categories.add(category) } } // 仅调用Adapter的setCategories即可,内部已处理刷新通知 categoryAdapter.setCategories(categories) Log.d("CategoryFragment", "RecyclerView updated. Item count: ${categoryAdapter.itemCount}") } // ... 其他代码保持不变
内容的提问来源于stack exchange,提问作者Kader Sutlu
相关产品推荐
相关产品推荐

