Android 为什么在更新firebase中的数据时,recyclerView中的数据会重复

Android 为什么在更新firebase中的数据时,recyclerView中的数据会重复,android,firebase,kotlin,firebase-realtime-database,android-recyclerview,Android,Firebase,Kotlin,Firebase Realtime Database,Android Recyclerview,如果我在firebase中有任何更改,如删除、更新。如果出现任何这些CRUD,recyclerView中的数据都会被复制,因此我添加了临时SwiperFresh来刷新活动,但这个解决方案没有意义 下图解释了我何时在firebase中更新数据以及在RecyclerView中发生了什么 main dashboard.kt 由于您正在使用addValueEventListener读取数据,这意味着: 路径中的数据会立即从数据库中读取,并传递到您的onDataChange 客户端将继续监视路径,如果有

如果我在firebase中有任何更改,如删除、更新。如果出现任何这些CRUD,recyclerView中的数据都会被复制,因此我添加了临时SwiperFresh来刷新活动,但这个解决方案没有意义

下图解释了我何时在firebase中更新数据以及在RecyclerView中发生了什么

main dashboard.kt


由于您正在使用
addValueEventListener
读取数据,这意味着:

  • 路径中的数据会立即从数据库中读取,并传递到您的
    onDataChange
  • 客户端将继续监视路径,如果有任何更改,它将使用路径上的所有数据再次调用您的
    onDataChange
  • 在您的
    onDataChange
    中,您只向
    patientDataItems
    添加数据。这在第一次加载数据时效果很好,因此上面的#1。但是,如果您添加或更改单个子节点(上面的#2),则会再次使用路径中的所有数据调用您。因此,当您复制视图中的项目时

    最简单的解决方案是在调用
    onDataChange
    时清除
    patientDataItems

    override fun onDataChange(p0: DataSnapshot) {
        patientDataItems.clear()
        ...
    

    清除数据容器,然后在recyclerview中再次绑定它。
    或者您有mvvm模式,您可以使用实时数据来观察数据源,如果有任何更改,您的活动将很容易得到通知并进行一些ui更改

    我在更新案例中这样做不起作用,但在添加中它需要最后一个元素并添加它,因此我需要刷新以查看我所做的操作如果我这样做了,实时数据库的好处是什么?
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.TextView
    import androidx.constraintlayout.widget.ConstraintLayout
    import androidx.recyclerview.widget.RecyclerView
    import com.example.ard_here.R
    
    class MainDashboardAdapter(private val patientDataSet: ArrayList<MainDashBoard.PatientDataItem>,
                               private val onPatientClickListener: OnItemPatientClickListener): RecyclerView.Adapter<MainDashboardAdapter.PatientCustomHolder>(){
    
    
        override fun getItemCount(): Int {
            return patientDataSet.size
        }
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PatientCustomHolder {
            var layoutInflater = LayoutInflater.from(parent?.context)
            var cellForRow = layoutInflater.inflate(R.layout.main_patient_layout, parent, false)
            return PatientCustomHolder(cellForRow)
        }
        override fun onBindViewHolder(holder: PatientCustomHolder, position: Int) {
            holder.bindItems(patientDataSet[position])
            holder.patientLayout.setOnClickListener {
                onPatientClickListener.onItemClick(patientDataSet[position])
            }
        }
    
    
        class PatientCustomHolder(v: View): RecyclerView.ViewHolder(v){
            val patientLayout: ConstraintLayout = v.findViewById(R.id.patient_layout)
            val patientName: TextView = v.findViewById(R.id.patient_name)
            val patientMessage : TextView = v.findViewById(R.id.patient_message)
            fun bindItems(data_item: MainDashBoard.PatientDataItem){
                patientName.text = data_item.patientName
                patientMessage.text = data_item.patientMessage
    
            }
        }
    }
    
    interface OnItemPatientClickListener {
        fun onItemClick(patientDataItems: MainDashBoard.PatientDataItem)
    }
    
    override fun onDataChange(p0: DataSnapshot) {
        patientDataItems.clear()
        ...