2016-08-21 4 views
2

Wenn ich eine neue Nachricht zu einem Listview hinzufüge, fügt das hinzu, dass ich die Nachricht und die neue Nachricht, so dass es die gleichen Informationen zweimal.Doppelte Objekte von Firebase in ListView geladen

ich letzte Nachrichten in einer Listenansicht mit Firebase geladen werden soll, ich die Follow-Funktion in erstellen muß():

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); 
     } 
    } 

Und für neue Nachricht hinzufügen:

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

Yeah !! Alles bereit –

Antwort

4

Wenn Sie addValueEventListener() verwenden, wird Ihr Handler sofort mit dem aktuellen Wert des Knotens aufgerufen und anschließend jedes Mal, wenn sich der Wert des Knotens ändert. Jedes Mal, wenn der Handler aufgerufen wird, erhält er einen Snapshot des gesamten Inhalts, auf den Sie achten. Also, wenn Sie mit 3-Nachrichten starten

message 1 
message 2 
message 3 

Ihr onDataChange() wird mit dieser 3-Nachricht aufgerufen erhalten. Wenn Sie dann eine vierte Nachricht hinzufügen:

message 1 
message 2 
message 3 
message 4 

Ihre onDataChange() wird mit allen 4-Nachrichten aufgerufen erhalten. Wenn Sie sich an Ihren aktuellen Code halten, müssen Sie die Duplikate selbst erkennen und entfernen.

Glücklicherweise ermöglicht das Firebase SDK auch durch Aufruf addChildEventListener(). Von der verlinkten Dokumentation:

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()); 
    } 
}); 

Wenn Sie diesen Ansatz verwenden, zunächst Ihr onChildAdded() 3 Mal aufgerufen werden, einmal für jedes Element. Wenn Sie dann das vierte Kind hinzufügen, werden Sie onChildAdded() erneut mit nur den 4. Artikel aufrufen.

0

Sie sollten nicht Fügen Sie Nachrichten auf andere Weise als vom Firebase-Listener hinzu, aber ich denke, Sie tun es in Zeile mCDataAdatapter.add(message.getText().toString()); nach dem Senden der Nachricht. Der Grund dafür ist, dass Firebase automatisch onDataChange aufruft, wenn Sie eine neue Nachricht selbst auf dem Client hinzufügen, der sie gesendet hat.

Ich würde auch empfehlen, ChildEventListener zu verwenden, andernfalls sollten Sie das ganze ListView löschen oder die Änderung filtern, um dieselben Daten zu vermeiden. Tust du es?