【问题标题】:How to change a single value in firebase database multiple times?如何多次更改firebase数据库中的单个值?
【发布时间】:2020-12-02 16:57:34
【问题描述】:

我正在尝试将 true 和 false 的值更改为相反的值,因此如果数据库中的值为 true,则需要将其更改为 false,如果为 false,则更改为 true。

它在我第一次按下按钮时工作,但如果我再次按下按钮,它会不停地变化,直到应用程序崩溃。

这是我用来更改值的代码:

package com.example.myapplication.adapters

import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.*
import androidx.recyclerview.widget.RecyclerView
import com.example.myapplication.Model.CategoryModel
import com.example.myapplication.R
import com.google.android.material.snackbar.Snackbar
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener

class Category(private val listCategory: MutableList<CategoryModel>) : 
RecyclerView.Adapter<Category.ViewHolder>() {

val mAuth = FirebaseAuth.getInstance()
val database = FirebaseDatabase.getInstance()
var currentUid = mAuth.currentUser?.uid
val myRef = database.getReference("User-following").child(currentUid!!)


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {

    val inflater = LayoutInflater.from(parent.context)
    val v = inflater.inflate(R.layout.category_layout, parent, false)
    return ViewHolder(v)
}


    private fun fetchNotificationStatus(category: String, b: Boolean) {

        var status = if (b) {
            "true"
        } else {
            "false"
        }

        myRef.addValueEventListener(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                for (childSnapshot in snapshot.children) {
                    val key = childSnapshot.key
                    if (childSnapshot.child("category").value == category) {
                        myRef.child(key!!).child("notifications").setValue(status)
                        return
                    }
                }
            }

            override fun onCancelled(error: DatabaseError) {
                Log.e("Database Error", error.toString())
            }
        })
    }







inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

    var category: TextView = itemView.findViewById(R.id.category)
    var remove: Button = itemView.findViewById(R.id.remove)
    val alert: CheckBox = itemView.findViewById(R.id.alert)



    init {
        alert.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
            val cat = category.text
            if (alert.isChecked) {
                 Snackbar.make(itemView,
                    "${category.text} has been added to your notifications list",
                    Snackbar.LENGTH_LONG)
                    .show()
                fetchNotificationStatus(cat as String, true)
            } else {
                Snackbar.make(itemView,
                    "${category.text} has been removed from your notifications list",
                    Snackbar.LENGTH_LONG)
                    .show()
                fetchNotificationStatus(cat as String, false)
            }
        }
    }
}

所以当你第一次按下复选框时,它会从

false -> True or from true -> false 

但如果你再次按下复选框,它会不断变化

 (false -> true -> false -> true -> false ...) 

并且在您关闭应用程序或按下另一个导致应用程序崩溃的按钮之前不会停止更改

我该如何解决这个问题,以便每次按下复选框时它只会变为相反的状态?

【问题讨论】:

  • 请编辑问题以显示所有相关代码。我们看不到fetchNotificationStatus 中的内容,也看不到写入数据库的任何代码。问题中需要有足够的信息,以便任何人都可以重现该行为。
  • 对不起我的错误,我已经在上面更新了。
  • 您的数据库侦听器通过写入它正在侦听的同一位置来触发自身。我建议重新考虑你想让这段代码做什么——这让我很困惑。
  • 每次按下复选框时,我都会尝试将值更改为相反的值,您能告诉我如何修复它吗?

标签: android kotlin firebase-realtime-database


【解决方案1】:

简单的解决方法是在fetchNotificationStatus 中使用addListenerForSingleValueEvent 而不是addValueEventListener。使用addListenerForSingleValueEvent 确保侦听器只获取一个值然后停止侦听。你当前的addValueEventListener 一直在监听数据,这样它就会被你自己的写入重新触发,然后它会一次又一次地写入它......


此外,我建议使用查询来查找要修改的节点:

private fun fetchNotificationStatus(category: String, b: Boolean) {

    var status = if (b) {
        "true"
    } else {
        "false"
    }

    Query query = myRef.orderByChild("category").equalTo(category);

    query.addListenerForSingleValueEvent(object : ValueEventListener {
        override fun onDataChange(snapshot: DataSnapshot) {
            for (childSnapshot in snapshot.children) {
                childSnapshot.getRef().child("notifications").setValue(status)
                // might be able to do .ref. instead of .getRef().
            }
        }

        override fun onCancelled(error: DatabaseError) {
            Log.e("Database Error", error.toString())
        }
    })
}

使用这样的查询可以减少您的应用读取的数据量,从而降低客户端和服务器上的带宽使用/成本。

【讨论】:

    猜你喜欢
    • 2017-11-28
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    • 2017-04-08
    • 2017-04-13
    • 1970-01-01
    • 2019-02-08
    相关资源
    最近更新 更多