Firebase Realtime Database绑定RecyclerView空状态检测问题求解
解决方案
核心问题排查
你遇到的计数不准、空状态检测失效问题,根源是现有代码的两个错误设计:
showbooks方法中遍历Firebase返回数据时,循环内重复创建Adapter、重复给RecyclerView绑定Adapter,导致onDataChange回调中获取到的Adapter还未完成数据绑定,计数完全失真。- 你将学院匹配过滤逻辑写在了Adapter的
bind方法中,且是异步请求后直接修改数据源,异步回调时机不可控,你在回调中读取计数时,过滤删数据的逻辑还未执行,自然拿不到正确值。
修改方案
步骤1:重构Adapter初始化逻辑,全局仅初始化一次
在Fragment中全局声明Adapter、数据源、空状态布局,仅在onViewCreated时初始化一次,后续数据变化仅更新数据源、通知Adapter刷新即可。
// Fragment全局变量 private lateinit var bookadapter: bookadapter private val booklist = arrayListOf<Booksmodel>() private lateinit var emptyView: View // 提前在Fragment布局中添加空状态提示布局
在onViewCreated中初始化Adapter,同时给Adapter添加数据变化观察者,自动监听数据变化检测空状态:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // 初始化Adapter,初始传入空列表 bookadapter = bookadapter(booklist, this@Books) bookrecyclerView.adapter = bookadapter // 监听Adapter数据变化,自动触发空状态检测 bookadapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { override fun onChanged() { super.onChanged() checkEmptyState() } override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) { super.onItemRangeRemoved(positionStart, itemCount) checkEmptyState() } override fun onItemRangeInserted(positionStart: Int, itemCount: Int) { super.onItemRangeInserted(positionStart, itemCount) checkEmptyState() } }) } // 封装空状态检测逻辑 private fun checkEmptyState() { val isListEmpty = bookadapter.itemCount == 0 bookrecyclerView.visibility = if (isListEmpty) View.GONE else View.VISIBLE emptyView.visibility = if (isListEmpty) View.VISIBLE else View.GONE }
步骤2:将过滤逻辑移到数据加载层,不要在Adapter中修改数据源
重写showbooks方法,先获取当前用户学院,再加载图书数据,提前校验图书所属用户的学院是否匹配,仅将符合条件的图书加入数据源:
private fun showbooks() { bookprogressbar.visibility = View.VISIBLE // 先获取当前用户所属学院 Mycollege.college(object : Mycollege.Mycallback { override fun onCallback(currentCollege: String) { databaseReference.addValueEventListener(object : ValueEventListener { @SuppressLint("NotifyDataSetChanged") override fun onDataChange(snapshot: DataSnapshot) { try { booklist.clear() // 无数据直接刷新空状态 if (!snapshot.hasChildren()) { bookadapter.notifyDataSetChanged() bookprogressbar.visibility = View.GONE return } for (item in snapshot.children) { val bookid = item.child("BookId").value.toString() val bookname = item.child("BookName").value.toString() val bookpublication = item.child("BookPublication").value.toString() val bookdept = item.child("Department").value.toString() val bookimage = item.child("BookImage").value.toString() val bookyear = item.child("BookYear").value.toString() val userid = item.child("UserUID").value.toString() val date = item.child("Date").value.toString() RedeleteBook(date, bookimage, bookid) // 提前校验图书所属用户的学院是否匹配 FirebaseDatabase.getInstance().getReference("Users") .child(userid) .get() .addOnSuccessListener { userSnapshot -> if (userSnapshot.exists()) { val userCollege = userSnapshot.child("College").value.toString() if (userCollege == currentCollege) { booklist.add( Booksmodel( bookid, bookimage, bookname, bookdept, bookpublication, bookyear, userid, ) ) bookadapter.notifyDataSetChanged() } } bookprogressbar.visibility = View.GONE } } } catch (e: Exception) { Toast.makeText(context, e.message, Toast.LENGTH_SHORT).show() bookprogressbar.visibility = View.GONE } } override fun onCancelled(error: DatabaseError) { Toast.makeText(context, "请检查网络连接", Toast.LENGTH_SHORT).show() bookprogressbar.visibility = View.GONE } }) } }) }
步骤3:精简Adapter逻辑,仅保留UI绑定功能
删除Adapter中bind方法里的学院校验、删数据逻辑,只做UI渲染:
// bookadapter.kt中修改bind方法 fun bind(book: Booksmodel, clicklistner: OnBookItemClicklistner) { // 仅保留UI渲染逻辑 if (searchText.isNotBlank()) { val highlightedText = book.BookName!!.replace( searchText, "<font color='red'>$searchText</font>", true ) bookname.text = HtmlCompat.fromHtml(highlightedText, HtmlCompat.FROM_HTML_MODE_LEGACY) } else { bookname.text = book.BookName } bookpublication.text = book.BookPublication bookdept.text = book.Department Picasso.get().load(book.BookImage).error(R.drawable.ic_action_book).into(bookimage) itemView.setOnClickListener { clicklistner.onBookItemclick(book) } } // onBindViewHolder同步修改 override fun onBindViewHolder(holder: bookholder, position: Int) { val book = booklist[position] holder.bind(book, itemClickListener) }
原有的搜索过滤filterlist方法无需修改,调用notifyDataSetChanged时会自动触发数据观察者,完成空状态检测。
内容的提问来源于stack exchange,提问作者Ashish Dawkhar
相关产品推荐
相关产品推荐

