从Firebase加载到ListView中的重复对象

时间:2016-08-21 20:56:53

标签: android firebase firebase-realtime-database

当我向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("");

        }


    }
});

2 个答案:

答案 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或过滤更改以避免相同的数据。你在做吗?