2016-07-12 28 views
3

Ich habe in der onCreate-Methode von Activity einen Wert-Ereignis-Listener eingerichtet. Bei dieser Methode protokolliere ich die Daten in der Konsole. Ich habe die Aktivität geöffnet und alles funktioniert gut. Aber wenn ich die Aktivität schließe und die Daten ändere, wird sie immer noch aufgerufen und ich kann das in Logs sehen.Kontext zu Firebase EventListener bereitstellen

Also, wenn ich diese Aktivität 5 Mal geöffnet habe, sehe ich bei jedem Update 5 Log-Nachrichten.

Gibt es keine Lösung, bei der wir einen Kontext für diese Aktivität bereitstellen können, sodass die Listener nach Abschluss der Aktivität abstürzen.

rootRef.addValueEventListener(new ValueEventListener() { 
      @Override 
      public void onDataChange(DataSnapshot dataSnapshot) { 
       Log.v(TAG, "Data Changed in Activity2"); 
      } 

      @Override 
      public void onCancelled(DatabaseError databaseError) { 

      } 
     }); 

Ich muss zu viele Wert Listeners in RecyclerView auch bereitstellen. Es verursacht auch mehrere Wert geändert Ereignisanrufe, nachdem es gescrollt wurde. Weil es eine neue Lügener an der vorhandenen Position binden und keine Referenz aus der onViewRecycled-Methode entfernen. Sie werden also mehrmals aufgerufen und ändern Daten zufällig auf dem Bildschirm.

Der Kontext erleichtert das Festlegen von Wert-Ereignis-Listenern. Kann ich auf diese Weise alle Zuhörer im Auge behalten? Es gibt auch keine Methode, die Listener als Referenz zu verwenden.

+1

Ich habe das gleiche Problem und endete damit, eine Liste von Referenzen auf Listener mit ihrem Kontext zu halten. Wenn der Kontext zerstört wird, durchlaufe ich alle Listener und entferne sie für sie. Schreckliche Lösung, aber es funktioniert. –

+0

Hallo Greg, kannst du erzählen, wie du eine Liste von Referenzen zu Hörern mit ihrem Kontext führst? Und wie entfernen, wenn Kontext zerstört wird? – kirtan403

+0

Überall in der App, wo ich einen Firebase-Listener hinzufüge, speichere ich ihn auch in einer ArrayList in einem Objekt zusammen mit dem zugehörigen Kontext/Aktivität und der Firebase-Abfrage. Wenn die Aktivität zerstört wird, gehe ich durch die Liste und rufe removeEventListener für die Abfrage auf. Es ist sehr zerbrechlich, aber ich weiß nicht, was ich sonst tun soll. –

Antwort

5

Da es derzeit keine Möglichkeit, einen Kontext Zuhörer zu schaffen, müssen den Überblick über alle angeschlossenen Hörer zu halten und entfernen Sie sie wie hier von David in der Antwort gezeigt: https://stackoverflow.com/a/33782474/1820644


Für Wert Zuhörer Verwaltung innerhalb der RecyclerView Ich habe eine Lösung gefunden, die gut funktioniert. Ich verwende RecyclerView von FirebaseUI, aber die Lösung sollte bei jedem RecyclerView funktionieren.

Schritt 1:

HashMap<String, ValueEventListener> mRecyclerViewFirebaseListeners = new HashMap<>(); 

Schritt 2: ValueEventListener in populateViewHolder (in firebaseUI) binden oder onBindViewHodler und fügen Sie es mRecyclerViewFirebaseListeners auf unsere Karte Erstens ein globales Map<String,ValueEventListener> in Ihrer Aktivität erstellen. Außerdem fügen Sie eine Tag Halter mit dem Wert unserer Schlüssel

protected void populateViewHolder(final ViewHolder viewHolder, 
            Boolean model, int position) { 

    Log.v(TAG, "Populating viewHolder for position: " + position); 

    // Get the key and add listener 
    String key = this.getRef(position).getKey(); 
    ValueEventListener listener = mRootRef.child("events").child(key) 
      .addValueEventListener(new ValueEventListener() { 
       public void onDataChange(DataSnapshot dataSnapshot) { 
        Log.v(TAG, "Event Data Change"); 
        // ... 
       } 

       @Override 
       public void onCancelled(DatabaseError databaseError) { 
        Log.v(TAG, databaseError.getMessage()); 
       } 
      }); 

    Log.v(TAG, "Listener set for event key: " + key + " (position: " + 
      position + ")"); 

    // Add to our map and set tag on view holder 
    mRecyclerViewFirebaseListeners.put(key, listener); 
    viewHolder.itemView.setTag(R.id.TAG_RCV_EVENT_KEY, key); 
    Log.d(TAG, "Added tag for position:" + position); 

    // do other work here 

} 

Schritt 3 anzuzeigen: Entfernen Sie einen Hörer für die Ansicht Halter, wenn eine Ansicht zurückgeführt wird.

@Override 
public void onViewRecycled(ViewHolder holder) { 
    super.onViewRecycled(holder); 

    // Get key from the view holder 
    String key = (String) holder.itemView.getTag(R.id.TAG_RCV_EVENT_KEY); 
    Log.v(TAG, "Recycling view set for key: " + key); 

    // Remove listener for the retrieved key and also remove it from our map 
    mRootRef.child("events").child(key) 
      .removeEventListener(mRecyclerViewFirebaseListeners.get(key)); 
    mRecyclerViewFirebaseListeners.remove(key); 
    Log.v(TAG, "On View Recycled, Removed Event listener for key: " + key); 

    // ... 

} 

Schritt 4: in restlichen Zuhörer entfernen onDestroy()

@Override 
public void onDestroyView() { 
    super.onDestroyView(); 

    // Iterate over map and remove listeners for the key 
    for (Map.Entry<String, ValueEventListener> entry : mRecyclerViewFirebaseListeners.entrySet()) { 
     String key = entry.getKey(); 
     ValueEventListener value = entry.getValue(); 
     mRootRef.child("events").child(key).removeEventListener(value); 
     Log.v(TAG, "Removed Event listener for key: " + key); 
    } 
} 

werden alle Ihre Zuhörer aus Recycler Ansicht dieses entfernen.

Wenn Sie andere Wert-Listener als recyclerview verwenden, verwenden Sie eine neue Map für die anderen, und kombinieren Sie sie in dieser Map, wenn sie mit dem Schlüsselmuster für den gleichen Pfad übereinstimmt.

Alternativ können Sie einen vollständigen Pfad anstelle eines Schlüssels als Schlüssel einer Map angeben.Wie im Beispiel haben wir Wert von "Schlüssel" unter dem Kind Ereignisse als der Schlüssel einer Karte verwendet, aber Sie können events/<key> als Schlüssel einer Karte setzen und auf einmal in onDestroy mit mRootRef.child("<your_combined_key_from_map>").removeListener(listener) entfernen.

Ich hoffe, das hilft jemandem.

Verwandte Themen