Reputation: 119
When I add new message to a listview, that adds message that I have and the new message, so it puts the same information twice.
I want to load last messages in a listview with Firebase, I have the follow function into create():
firebase = new Firebase(FIREBASE_URL).child(FIREBASE_CHILD + "/" + sharedPreferences.getString("chatKey", null).toString() + "/room/");
firebase.child("messages").addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot Snapshot) {
if (Snapshot.getValue() != null) {
Iterable<DataSnapshot> iterator = Snapshot.getChildren();
itemMessage itemData;
for(DataSnapshot value : iterator){
itemData = value.getValue( itemMessage.class );
mCDataAdatapter.add( itemData.getMessage().toString() );
}
mConversation.setAdapter( mCDataAdatapter );
}
}
And for add new message:
sendMessage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(ChatActivity.this);
SharedPreferences.Editor editor = sharedPreferences.edit();
// editor.clear().commit();
if( sharedPreferences.getString("chatKey", null) != null && sharedPreferences.getString("chatKey", null).toString() != "" ){
messageLevel = new Firebase(FIREBASE_URL+sharedPreferences
.getString("chatKey", null)
.toString()+"/room/")
.child("messages");
Map<String, Object> messageData = new HashMap<String, Object>();
messageData.put( "message", message.getText().toString() );
messageData.put( "userTo", 1 );
messageData.put( "userFrom",2 );
messageLevel
.push()
.setValue(messageData);
mCDataAdatapter.add( message.getText().toString() );
mConversation.setAdapter( mCDataAdatapter );
message.setText("");
}
}
});
Upvotes: 2
Views: 3152
Reputation: 9008
You shouldn't add messages any other way than by Firebase listener, but I guess you are doing it at line mCDataAdatapter.add( message.getText().toString() );
after sending the message. The reason is that Firebase will automatically call onDataChange
when you add new message even on client who sent it.
I would also recommend using ChildEventListener
, otherwise you should clear the whole ListView
or filter the change to avoid same data. Are you doing it?
Upvotes: 0
Reputation: 598901
When you use addValueEventListener()
, your handler will be invoked immediately with the current value of the node and subsequently each time the value of the node changes. Each time the handler is invoked, it gets a snapshot of the entire contents that you listen for. So if you start with 3 messages
message 1
message 2
message 3
Your onDataChange()
will get invoked with these 3 message. If you then add a 4th message:
message 1
message 2
message 3
message 4
Your onDataChange()
will get invoked with all 4 messages. If you stick to your current code, you will have to detect and remove the duplicates yourself.
Luckily the Firebase SDK also allows you to listen for child level changes by calling addChildEventListener()
. From the linked documentation:
ref.addChildEventListener(new ChildEventListener() {
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());
// A new comment has been added, add it to the displayed list
Comment comment = dataSnapshot.getValue(Comment.class);
}
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());
// A comment has changed, use the key to determine if we are displaying this
// comment and if so displayed the changed comment.
Comment newComment = dataSnapshot.getValue(Comment.class);
String commentKey = dataSnapshot.getKey();
}
public void onChildRemoved(DataSnapshot dataSnapshot) {
Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());
// A comment has changed, use the key to determine if we are displaying this
// comment and if so remove it.
String commentKey = dataSnapshot.getKey();
}
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());
// A comment has changed position, use the key to determine if we are
// displaying this comment and if so move it.
Comment movedComment = dataSnapshot.getValue(Comment.class);
String commentKey = dataSnapshot.getKey();
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "postComments:onCancelled", databaseError.toException());
}
});
If you use this approach, initially your onChildAdded()
will be called 3 times, once for each item. Then when you add the 4th child, you onChildAdded()
will be invoked again with just the 4th item.
Upvotes: 5