Since you say that the button can be clicked by multiple users, there might be a situation in which two or even more users can click the button simultaneously. This means that you should implement a mechanism that can allow you to have consistent data. This can be done using transactions, as explained in my answer from the following post:
However, since a button click will always increment the counter by one, please see below an even simpler atomic solution:
button.setOnClickListener {
rootRef.child("counter").setValue(ServerValue.increment(1))
}
Edit:
You are getting the following error:
UninitializedPropertyAccessException: lateinit property rootRef has not been initialized
Because by the time you are using the rootRef
the is not yet object initialized. So please make sure you call first:
val rootRef = FirebaseDatabase.getInstance().reference
Edit2:
I've seen you have added a similar question here. Maybe I didn't understand that in the first place, but you cannot update a counter atomically using a model Total
class. There is no need for that. It's true that you can read the data and update it using a transaction, but for a simple increment, you should only use the above code. That means that you can only take a reference of the field that needs to be incremented and that's it. No need for any model classes. Model classes are used when you want to map an object from the database into an object of the particular class.
Edit3:
To display the newly added counter, please use the following lines of code:
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)
The output will always be the value of the incremented counter
.
Edit4:
This is all you need:
//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)
}
Edit5:
When you remove:
private var database : DatabaseReference = FirebaseDatabase.getInstance().getReference("IncrementButton")
It makes sense to get this error:
"unresolved reference: database"
As the line of code:
database.child("pressed").setValue(ServerValue.increment(1))
Because this line is notcorrect. It should be:
pressedRef.setValue(ServerValue.increment(1))
// ^ ^ See the reference?
So use the exact code I have provided in the Edit4, nothing else. Besides that, your schema should look like this:
Firebase-root
|
--- pressed: 2 <- Not counter, not anything else. Just "pressed"
In this way, you won't get:
"Button has been pressed null times!"
You certainly get:
"Button has been pressed 2 times!"