android - 如何保存所有用户的按键次数并在屏幕上显示总数
问题描述
该应用程序已连接到 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)
解决方案
既然你说按钮可以被多个用户点击,那么可能会出现两个甚至更多用户同时点击按钮的情况。这意味着您应该实现一种可以让您拥有一致数据的机制。这可以使用事务来完成,正如我在以下帖子中的回答中所解释的那样:
但是,由于单击按钮总是会使计数器加一,请参见下面更简单的原子解决方案:
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!"
推荐阅读
- docker - 无法更新对象类型 *libnetwork.endpointCnt 的存储:在存储中找不到密钥
- r - 从数据框列表中创建一个输出文件,其中包含每个数据框的特定名称和维度
- react-native - 在本机反应中从数组中查找和替换键
- java - 如何在java中删除日志文件中的日期和时间
- javascript - 基于滚动触发背景图像的更好方法
- java - 如何使用自定义消息记录肥皂请求和响应以在 Spring Boot 中归档?
- r - R:删除具有 2 列中文本条件组合的行
- apache-spark - PySpark - 列出特定文件和目录
- keycloak - 注册自动登录禁用
- javascript - 查询 mongodb 获取最近 30 分钟内创建的文档