You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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


修复方案

核心问题定位

  1. ViewHolder中TextView绑定逻辑错误:
    ViewHolder里将textViewTrName绑定到了R.id.textViewCategoryEn,textViewEnName绑定到了R.id.textViewCategoryTr,同时在bind方法中又把category.tr赋值给textViewTrName、category.en赋值给textViewEnName,导致数据与UI控件的对应关系混乱,即使数据更新也无法正确显示。
  2. 重复调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 12:59:56