3

Another event triggering problem from Firebase.

I have the class Post which contain a properties that store Timestamp like below:

public class Post {

    public int likeCount;
    private Long createDate;
    public String createBy;

    public java.util.Map<String, String> getCreationDate() {
        return ServerValue.TIMESTAMP;
    }

    @Exclude
    public Long getCreateDateLong() {
        return createDate;
    }

    public Post() {
    }
}

When i add a new post to firebase-database like below:

Post newPost = new Post();
newPost.createBy = firebaseAuth.getCurrentUser().getUid();
databaseReference.child("posts").push().setValue(newPost);

The onDataChanged for ValueEventListener() will trigger twice, and the onChildAdded and onChildChanged for ChildEventListener() will be triggered one after another.

I suspect this is because the ServerValue.TIMESTAMP actually caused the createDate to update after the creation of the child.

This is a very annoying and unexpected behaviour to deal with. It should have trigger just once.

I'm getting sick of these problems. Is it a right decision to go with Firebase Database in the first place? sigh...


[Update]
The behavior is clearly explained by Frank here.

However, is there common pattern to handle this behavior? In the situation that I have the listener setup and do something to the UI when data change. Then I insert a new record with a timestamp in it. What happen next is that my UI actually have to do something twice for one single insert event.

I understand that there is a addListenerForSingleValueEvent, but the reason i use don't it is because i also handle update of data from anywhere similarly. If I use addListenerForSingleValueEvent i will have to remove the ValueEventListener before i insert, then add it back after insert done. This doesn't seems right to me.

Is there anything in the event callback that i can use to determine weather or not it is a change that i care and want to do something about? Did i missed something?

Community
  • 1
  • 1
Terrence
  • 2,189
  • 1
  • 15
  • 12
  • 1
    Have you tryied `addListenerForSingleValueEvent`? – adolfosrs Jun 20 '16 at 18:06
  • 2
    Writing a `ServerValue.TIMESTAMP` is expected to fire two value events: one for the local estimate, then once more once the confirmation comes back from the server. I answered this before, I'll find the duplicate. – Frank van Puffelen Jun 20 '16 at 18:29
  • See http://stackoverflow.com/questions/37864974/how-to-use-the-firebase-server-timestamp-to-generate-date-created/37868163#37868163 – Frank van Puffelen Jun 20 '16 at 18:31
  • According to what @FrankvanPuffelen wrote you could maybe ignore the first callback of value change (the client's guess) and only perform your logic on the second event (the server response). Otherwise leave the addValueEventListener() registered until two consecutive responses contain same value. Once that happens use removeEventListener() to remove that listener and run your logic. – Voy Jun 21 '16 at 09:15
  • 1
    @Voy yeah, i would like to ignore the first callback. But how? How do I know that the first callback is fire because of the Timestamp (client's guess). Sorry if i'm asking stupid question. May be i miss out something obvious. – Terrence Jun 21 '16 at 11:51
  • Depending on your case there may be different methods you could use, my suggestions are: One would be to store a member field counter and increment on every response (or until you verify you're getting a server response). Another way is to store each response as a member field and compare each new response to the previous one. If two are equal then you know it is the server response (as only client guess compared with server response could differ) and you can remove the listener and do the logic. This may depend on your particular case like I said, you will not always get more than 2 responces – Voy Jun 21 '16 at 16:47

0 Answers0