当我向listview添加新消息时,会添加我拥有的消息和新消息,因此它会将相同的信息放两次。
我想在使用Firebase的listview中加载最后一条消息,我将以下函数放入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 );
}
}
并添加新消息:
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("");
}
}
});
答案 0 :(得分:5)
当您使用addValueEventListener()
时,将立即使用节点的当前值调用您的处理程序,并且随后每次节点的值更改时。每次调用处理程序时,它都会获取您侦听的整个内容的快照。所以,如果你从3条消息开始
message 1
message 2
message 3
将使用这3条消息调用您的onDataChange()
。如果您再添加第4条消息:
message 1
message 2
message 3
message 4
将使用所有4条消息调用您的onDataChange()
。如果您坚持使用当前代码,则必须自己检测并删除重复项。
幸运的是,Firebase SDK还允许您通过调用addChildEventListener()
listen for child level changes来{{3}}。来自链接文档:
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());
}
});
如果您使用此方法,最初您的onChildAdded()
将被调用3次,每个项目一次。然后,当您添加第4个孩子时,将再次使用第4个项目调用onChildAdded()
。
答案 1 :(得分:0)
除了Firebase侦听器之外,您不应该以任何其他方式添加消息,但我猜您在发送消息后在行mCDataAdatapter.add( message.getText().toString() );
处执行此操作。原因是,即使在发送新邮件的客户端上,Firebase也会自动调用onDataChange
。
我还建议您使用ChildEventListener
,否则您应该清除整个ListView
或过滤更改以避免相同的数据。你在做吗?