ChildEventListener onChildAdded triggered prematurely in Android.

681 views
Skip to first unread message

sherwin de jesus

unread,
Jun 21, 2016, 10:21:24 AM6/21/16
to Firebase Google Group
Im trying to create a group chat application using Firebase.

On my onCreate, I have this:
chatMessageEditText = (EditText) findViewById(R.id.message);
chatMessageEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId==EditorInfo.IME_ACTION_SEND) {
// Send new group chat message
String key = fbChatRef.push().getKey();
fbChatRef.child(key).child("sender_uid").setValue(fbUser.getUid());
fbChatRef.child(key).child("sender_name").setValue(fbUser.getDisplayName());
fbChatRef.child(key).child("timestamp").setValue( (new Date()).toString() );
fbChatRef.child(key).child("message").setValue(v.getText().toString());

v.setText("");

return true;
} else {
return false;
}
}
});

Then on when user join a group, I have this:
// Listen to group chat
fbChatEventListener = new ChildEventListener() {
@Override

public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ChatMessage localChatMessage = new ChatMessage();
localChatMessage.sender_name = dataSnapshot.child("sender_name").getValue().toString();
localChatMessage.message_date = dataSnapshot.child("timestamp").getValue().toString();
localChatMessage.message = dataSnapshot.child("message").getValue().toString();
localChatMessage.sender_uid = dataSnapshot.child("sender_uid").getValue().toString();
chatMessages.add(localChatMessage);

chatMessageAdapter.notifyDataSetChanged();

Log.d(TAG + "Chat:onChildAdded", "From:" + dataSnapshot.child("sender_name").getValue().toString() +
" " + dataSnapshot.child("timestamp").getValue().toString() +
"\n" + dataSnapshot.child("message").getValue().toString());
}

@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}

@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {

}

@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {

}

@Override
public void onCancelled(DatabaseError databaseError) {

}
};
fbChatRef.orderByKey();
fbChatRef.addChildEventListener(fbChatEventListener);


First off, I have prevented the user to send a message without first joining a group.

When  setOnEditorActionListener is triggered, the dataSnapshot.child("sender_name") inside the onChildAdded is null when in fact, I have set it on setOnEditorActionListener. Thus I suspected that the onChildAdded is trigger prematurely.

Can somebody pls help me with this.


Frank van Puffelen

unread,
Jun 21, 2016, 11:33:56 PM6/21/16
to Firebase Google Group
You're performing 4 separate write actions to the database:

            fbChatRef.child(key).child("sender_uid").setValue(fbUser.getUid());
fbChatRef.child(key).child("sender_name").setValue(fbUser.getDisplayName());
fbChatRef.child(key).child("timestamp").setValue( (new Date()).toString() );
fbChatRef.child(key).child("message").setValue(v.getText().toString());

That first setValue() will already trigger the onChildAdded() method of your listener, which then tries to read a child property that doesn't exist yet:

         localChatMessage.sender_name = dataSnapshot.child("sender_name").getValue().toString();

The subsequent setValue() calls will trigger onChildChanged(), which your code is not handling.

The proper way to handle this is to write all the child properties of the message with a single setValue() operation
Our documentation on saving data on Android has some good examples of using a Java object to represent your data.
Since you already have a Java class for the ChatMessage, it could be as simple as:

    ChatMessage msg = new ChatMessage(fbUser.getUid(), fbUser.getDisplayName(), new Date()).toString(), v.getText().toString());
    fbChatRef.push().setValue(msg);

Now the entire write happens in one operation, so the onChildAdded() is triggered with the complete snapshot it expects.

    puf
Reply all
Reply to author
Forward
0 new messages