首页 > 解决方案 > 如何保存所有用户的按键次数并在屏幕上显示总数

问题描述

该应用程序已连接到 Firebase,并使用免费 spark 计划中的实时数据库。该应用程序基于 kotlin。

此代码正确存储了所有设备上的按钮按下次数,并在应用程序重新启动后保存了按下次数,但是我无法从数据库中检索按钮被按下的次数,以显示在屏幕上。


    //private var database : DatabaseReference = FirebaseDatabase.getInstance().getReference("IncrementButton")
    
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_second)

    val rootRef = FirebaseDatabase.getInstance().reference
    val pressedRef = rootRef.child("pressed")

    button_increment.setOnClickListener {
        pressedRef.setValue(ServerValue.increment(1));
    }

    val valueEventListener = object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            val pressed = dataSnapshot.getValue(Long::class.java)
            Log.d("TAG", "Button has been pressed $pressed times!")
        }

        override fun onCancelled(databaseError: DatabaseError) {
            Log.d("TAG", databaseError.getMessage()) //Don't ignore potential errors!
        }
    }
    pressedRef.addValueEventListener(valueEventListener)
}

这是我的数据类中的内容:

data class IncrementButton(val pressed : Int? = null)

标签: androidfirebasekotlin

解决方案


既然你说按钮可以被多个用户点击,那么可能会出现两个甚至更多用户同时点击按钮的情况。这意味着您应该实现一种可以让您拥有一致数据的机制。这可以使用事务来完成,正如我在以下帖子中的回答中所解释的那样:

但是,由于单击按钮总是会使计数器加一,请参见下面更简单的原子解决方案:

button.setOnClickListener { 
    rootRef.child("counter").setValue(ServerValue.increment(1))
}

编辑:

您收到以下错误:

UninitializedPropertyAccessException:lateinit 属性 rootRef 尚未初始化

因为到您使用时,rootRef尚未初始化对象。所以请确保你先打电话:

val rootRef = FirebaseDatabase.getInstance().reference

编辑2:

我看到你在这里添加了一个类似的问题。也许我一开始就不明白,但你不能使用模型Total类原子地更新计数器。没有必要这样做。确实可以使用事务读取数据并对其进行更新,但是对于简单的增量,您应该只使用上面的代码。这意味着您只能引用需要递增的字段,仅此而已。不需要任何模型类。当您要将数据库中的对象映射到特定类的对象时,使用模型类。

编辑3:

要显示新添加的计数器,请使用以下代码行:

val rootRef = FirebaseDatabase.getInstance().reference
val counterRef = rootRef.child("counter")
val valueEventListener = object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        val counter = dataSnapshot.getValue(Long::class.java)
        Log.d("TAG", "counter: $counter")
    }

    override fun onCancelled(databaseError: DatabaseError) {
        Log.d("TAG", databaseError.getMessage()) //Don't ignore potential errors!
    }
}
counterRef.addValueEventListener(valueEventListener)

输出将始终是 incremented 的值counter

编辑4:

这就是你所需要的:

//private lateinit var pressed : IncrementButton
//private var database : DatabaseReference = FirebaseDatabase.getInstance().getReference("IncrementButton")


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_second)

    val rootRef = FirebaseDatabase.getInstance().reference
    val pressedRef = rootRef.child("pressed")

    button_increment.setOnClickListener {
        pressedRef.setValue(ServerValue.increment(1));
    }

    val valueEventListener = object : ValueEventListener {
        override fun onDataChange(dataSnapshot: DataSnapshot) {
            val pressed = dataSnapshot.getValue(Long::class.java)
            Log.d("TAG", "Button has been pressed $pressed times!")
        }

        override fun onCancelled(databaseError: DatabaseError) {
            Log.d("TAG", databaseError.getMessage()) //Don't ignore potential errors!
        }
    }
    pressedRef.addValueEventListener(valueEventListener)
}

编辑5:

当您删除:

private var database : DatabaseReference = FirebaseDatabase.getInstance().getReference("IncrementButton")

得到这个错误是有道理的:

“未解决的参考:数据库”

作为代码行:

database.child("pressed").setValue(ServerValue.increment(1))

因为这条线是正确的。它应该是:

pressedRef.setValue(ServerValue.increment(1))
// ^ ^ See the reference?

因此,请使用我在Edit4中提供的确切代码,仅此而已。除此之外,您的架构应如下所示:

Firebase-root
  |
  --- pressed: 2 <- Not counter, not anything else. Just "pressed"

这样,您将不会得到:

"Button has been pressed null times!"

你肯定会得到:

"Button has been pressed 2 times!"

推荐阅读