Mit Datenlisten auf Android-Geräten arbeiten

In diesem Dokument erfahren Sie, wie Sie in Firebase mit Datenlisten arbeiten. Informationen zu den Grundlagen des Lesens und Schreibens von Firebase-Daten finden Sie unter Daten auf Android-Geräten lesen und schreiben.

Datenbankreferenz abrufen

Zum Lesen und Schreiben von Daten aus der Datenbank benötigen Sie eine Instanz von DatabaseReference:

Kotlin+KTX

private lateinit var database: DatabaseReference
// ...
database = Firebase.database.reference

Java

private DatabaseReference mDatabase;
// ...
mDatabase = FirebaseDatabase.getInstance().getReference();

Listen lesen und schreiben

An eine Datenliste anhängen

Verwenden Sie die Methode push(), um Daten an eine Liste in Anwendungen mit mehreren Nutzern anzuhängen. Die Methode push() generiert jedes Mal einen eindeutigen Schlüssel, wenn ein neuer Schlüssel wird der angegebenen Firebase-Referenz hinzugefügt. Mit diesen automatisch generierten Schlüssel für jedes neue Element in der Liste, können mehrere Clients fügen Sie untergeordnete Elemente ohne Schreibkonflikte gleichzeitig demselben Speicherort hinzu. Die Der von push() generierte eindeutige Schlüssel basiert auf einem Zeitstempel. Listenelemente werden daher automatisch chronologisch sortiert.

Sie können den Verweis auf die neuen Daten verwenden, die von der Methode push() zurückgegeben werden, um Wert des automatisch generierten Schlüssels oder Satzdaten des untergeordneten Elements. Anrufen getKey() in einer push()-Referenz gibt den Wert von automatisch generierten Schlüssel.

Sie können diese automatisch generierten Schlüssel verwenden, um die Aufschlüsselung Ihrer Daten zu vereinfachen Struktur. Weitere Informationen finden Sie im Abschnitt zum Daten-Fächer-Out. Beispiel:

Auf untergeordnete Ereignisse warten

Wenn Sie mit Listen arbeiten, sollte Ihre Anwendung auf untergeordnete Ereignisse achten und nicht auf die Wert-Ereignisse, die für einzelne Objekte verwendet werden.

Untergeordnete Ereignisse werden als Reaktion auf bestimmte Vorgänge ausgelöst, die Untergeordnete Elemente eines Knotens aus einem Vorgang wie einem neuen untergeordneten Element, das über die push()-Methode oder ein untergeordnetes Element, das über die updateChildren()-Methode aktualisiert wird. Diese Kombination kann nützlich sein, um Änderungen an einem bestimmten Knoten zu überwachen. in einer Datenbank.

Um auf untergeordnete Ereignisse in DatabaseReference zu warten, fügen Sie ein ChildEventListener:

Listener Ereignis-Callback Normale Nutzung
ChildEventListener onChildAdded() Rufen Sie Listen von Elementen ab oder achten Sie auf Ergänzungen zu einer Liste von Elementen. Dieser Callback wird für jedes vorhandene untergeordnete Element einmal und dann noch einmal ausgelöst. jedes Mal, wenn dem angegebenen Pfad ein neues untergeordnetes Element hinzugefügt wird. Die an den Listener übergebene DataSnapshot enthält den die Daten des neuen Kindes.
onChildChanged() Beobachten Sie Änderungen an den Elementen in einer Liste. Dieses Ereignis wurde jedes Mal ausgelöst, wenn ein der untergeordnete Knoten geändert wird, einschließlich aller Änderungen an Nachkommen von dem untergeordneten Knoten. An das Ereignis übergebene DataSnapshot Listener enthält die aktualisierten Daten für das untergeordnete Element.
onChildRemoved() Prüfen, ob Elemente aus einer Liste entfernt werden Die DataSnapshot, die an den Ereignis-Callback übergeben wurde, enthält Folgendes: Daten für das entfernte Kind.
onChildMoved() Beobachten Sie Änderungen an der Reihenfolge der Elemente in einer geordneten Liste. Dieses Ereignis wird ausgelöst, wenn onChildChanged() Callback wird durch ein Update ausgelöst, das eine Neuanordnung des untergeordneten Elements bewirkt. Sie wird für Daten verwendet, die mit orderByChild oder orderByValue sortiert sind.

Diese Methoden können beispielsweise in einer Blog-App für soziale Netzwerke eingesetzt werden. um die Aktivitäten in den Kommentaren zu einem Beitrag zu überwachen:

Kotlin+KTX

val childEventListener = object : ChildEventListener {
    override fun onChildAdded(dataSnapshot: DataSnapshot, previousChildName: String?) {
        Log.d(TAG, "onChildAdded:" + dataSnapshot.key!!)

        // A new comment has been added, add it to the displayed list
        val comment = dataSnapshot.getValue<Comment>()

        // ...
    }

    override fun onChildChanged(dataSnapshot: DataSnapshot, previousChildName: String?) {
        Log.d(TAG, "onChildChanged: ${dataSnapshot.key}")

        // A comment has changed, use the key to determine if we are displaying this
        // comment and if so displayed the changed comment.
        val newComment = dataSnapshot.getValue<Comment>()
        val commentKey = dataSnapshot.key

        // ...
    }

    override fun onChildRemoved(dataSnapshot: DataSnapshot) {
        Log.d(TAG, "onChildRemoved:" + dataSnapshot.key!!)

        // A comment has changed, use the key to determine if we are displaying this
        // comment and if so remove it.
        val commentKey = dataSnapshot.key

        // ...
    }

    override fun onChildMoved(dataSnapshot: DataSnapshot, previousChildName: String?) {
        Log.d(TAG, "onChildMoved:" + dataSnapshot.key!!)

        // A comment has changed position, use the key to determine if we are
        // displaying this comment and if so move it.
        val movedComment = dataSnapshot.getValue<Comment>()
        val commentKey = dataSnapshot.key

        // ...
    }

    override fun onCancelled(databaseError: DatabaseError) {
        Log.w(TAG, "postComments:onCancelled", databaseError.toException())
        Toast.makeText(
            context,
            "Failed to load comments.",
            Toast.LENGTH_SHORT,
        ).show()
    }
}
databaseReference.addChildEventListener(childEventListener)

Java

ChildEventListener childEventListener = new ChildEventListener() {
    @Override
    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);

        // ...
    }

    @Override
    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();

        // ...
    }

    @Override
    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();

        // ...
    }

    @Override
    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());
        Toast.makeText(mContext, "Failed to load comments.",
                Toast.LENGTH_SHORT).show();
    }
};
databaseReference.addChildEventListener(childEventListener);

Auf Wertereignisse warten

Wir empfehlen die Verwendung von ChildEventListener, um Listen kann es vorkommen, dass ValueEventListener an eine Liste angehängt wird, Referenz ist nützlich.

Wenn Sie eine ValueEventListener an eine Datenliste anhängen, wird die gesamte Liste mit Daten als einzelne DataSnapshot, auf die Sie dann auf einzelne Kinder zugreifen.

Auch wenn es nur eine einzige Übereinstimmung für die Abfrage gibt, ist der Snapshot trotzdem ein Liste; enthält sie nur ein einzelnes Element. Um auf das Element zuzugreifen, musst du das Ergebnis durchlaufen:

Kotlin+KTX

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        for (postSnapshot in dataSnapshot.children) {
            // TODO: handle the post
        }
    }

    override fun onCancelled(databaseError: DatabaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
        // ...
    }
})

Java

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
            // TODO: handle the post
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
        // ...
    }
});

Dieses Muster kann nützlich sein, wenn Sie alle untergeordneten Elemente einer Liste abrufen möchten in einem einzigen Vorgang ausführen, anstatt zusätzliche onChildAdded zu überwachen Ereignisse.

Listener trennen

Callbacks werden durch Aufrufen der removeEventListener()-Methode auf Ihrem Firebase-Datenbankreferenz

Wenn ein Listener einem Datenspeicherort mehrmals hinzugefügt wurde, wird er für jedes Ereignis mehrmals aufgerufen. Sie müssen ihn also genauso oft trennen, um ihn vollständig zu entfernen.

Das Aufrufen von removeEventListener() für einen übergeordneten Listener erfolgt nicht Listener, die auf den untergeordneten Knoten registriert sind, werden automatisch entfernt. removeEventListener() muss auch für alle untergeordneten Listener aufgerufen werden um den Callback zu entfernen.

Daten sortieren und filtern

Mit der Klasse Realtime Database Query können Sie Daten abrufen, die nach folgenden Kriterien sortiert sind: nach Schlüssel, nach Wert oder nach Wert eines untergeordneten Elements. Sie können auch das sortierte Ergebnis auf eine bestimmte Anzahl von Ergebnissen, einen Schlüsselbereich oder Werte.

Daten sortieren

Um sortierte Daten abzurufen, geben Sie zunächst eine der Sortiermethoden an, wie die Ergebnisse sortiert werden:

Methode Nutzung
orderByChild() Sortiert die Ergebnisse nach dem Wert eines angegebenen untergeordneten Schlüssels oder verschachtelten untergeordneten Pfads.
orderByKey() Sortieren Sie die Ergebnisse nach untergeordneten Schlüsseln.
orderByValue() Sortieren Sie die Ergebnisse nach untergeordneten Werten.

Sie können jeweils nur eine Sortiermethode verwenden. Wenn Sie eine Methode zum Sortieren mehrmals in derselben Abfrage aufrufen, wird ein Fehler ausgegeben.

Im folgenden Beispiel wird gezeigt, wie du eine Liste der Top-Beiträge eines Nutzers abrufen kannst, sortiert nach der Anzahl der Sterne:

Kotlin+KTX

// My top posts by number of stars
val myUserId = uid
val myTopPostsQuery = databaseReference.child("user-posts").child(myUserId)
    .orderByChild("starCount")

myTopPostsQuery.addChildEventListener(object : ChildEventListener {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
})

Java

// My top posts by number of stars
String myUserId = getUid();
Query myTopPostsQuery = databaseReference.child("user-posts").child(myUserId)
        .orderByChild("starCount");
myTopPostsQuery.addChildEventListener(new ChildEventListener() {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
});

Definiert eine Abfrage, die in Kombination mit einem untergeordneten Listener synchronisiert den Client mit den Beiträgen des Nutzers aus dem Pfad in der Datenbank basierend auf der Nutzer-ID, sortiert nach der Anzahl der Sterne, die jeder Beitrag erhalten hat. Diese Technik zur Verwendung von IDs als Indexschlüssel wird als Data-Fan-Out bezeichnet. Sie können mehr darüber in Datenbank strukturieren

Der Aufruf der Methode orderByChild() gibt den untergeordneten Schlüssel zum Sortieren der Ergebnisse nach. In diesem Fall werden Beiträge nach dem Wert ihrer jeweiligen "starCount" Kind. Abfragen können auch nach verschachtelten Kinder, wenn Sie Daten haben, die wie folgt aussehen:

"posts": {
  "ts-functions": {
    "metrics": {
      "views" : 1200000,
      "likes" : 251000,
      "shares": 1200,
    },
    "title" : "Why you should use TypeScript for writing Cloud Functions",
    "author": "Doug",
  },
  "android-arch-3": {
    "metrics": {
      "views" : 900000,
      "likes" : 117000,
      "shares": 144,
    },
    "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
    "author": "Doug",
  }
},

In diesem Beispiel können wir unsere Listenelemente nach Werten sortieren, die unter dem Schlüssel metrics verschachtelt sind, indem wir den relativen Pfad zum verschachtelten untergeordneten Element in unserem orderByChild()-Aufruf angeben.

Kotlin+KTX

// Most viewed posts
val myMostViewedPostsQuery = databaseReference.child("posts")
    .orderByChild("metrics/views")
myMostViewedPostsQuery.addChildEventListener(object : ChildEventListener {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
})

Java

// Most viewed posts
Query myMostViewedPostsQuery = databaseReference.child("posts")
        .orderByChild("metrics/views");
myMostViewedPostsQuery.addChildEventListener(new ChildEventListener() {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
});

Weitere Informationen zur Anordnung anderer Datentypen finden Sie unter Sortierung von Abfragedaten

Daten filtern

Zum Filtern von Daten können Sie beliebige Grenzwert- oder Bereichsmethoden mit einem -Methode beim Erstellen einer Abfrage.

Methode Nutzung
limitToFirst() Legt die maximale Anzahl von Elementen fest, die ab Beginn des sortierte Ergebnisliste.
limitToLast() Legt die maximale Anzahl der Artikel fest, die ab dem Ende des bestellten Artikels zurückgegeben werden. Liste der Ergebnisse.
startAt() Gibt Elemente zurück, die größer oder gleich dem angegebenen Schlüssel oder Wert sind abhängig von der gewählten Order-by-Methode.
startAfter() Gibt Elemente zurück, die größer als der angegebene Schlüssel oder Wert sind abhängig von der gewählten Order-by-Methode.
endAt() Gibt Elemente zurück, die kleiner oder gleich dem angegebenen Schlüssel oder Wert sind, je nach ausgewählter Sortiermethode.
endBefore() Gibt Elemente zurück, die kleiner als der angegebene Schlüssel oder Wert sind abhängig von der gewählten Order-by-Methode.
equalTo() Je nach ausgewählter Sortiermethode werden Elemente zurückgegeben, die dem angegebenen Schlüssel oder Wert entsprechen.

Im Gegensatz zu den Sortiermethoden können Sie mehrere Limit- oder Bereichsfunktionen kombinieren. Sie können beispielsweise die Methoden startAt() und endAt() kombinieren, um in einen bestimmten Wertebereich eingeben.

Auch wenn es nur eine Übereinstimmung für die Abfrage gibt, ist der Snapshot immer eine Liste, die nur ein Element enthält. Für den Zugriff auf das Element benötigen Sie um das Ergebnis zu durchlaufen:

Kotlin+KTX

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        for (postSnapshot in dataSnapshot.children) {
            // TODO: handle the post
        }
    }

    override fun onCancelled(databaseError: DatabaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
        // ...
    }
})

Java

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
            // TODO: handle the post
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
        // ...
    }
});

Anzahl der Ergebnisse begrenzen

Sie können die Methoden limitToFirst() und limitToLast() verwenden, um eine Maximale Anzahl von untergeordneten Elementen, die für einen bestimmten Callback synchronisiert werden sollen. Wenn beispielsweise Sie limitToFirst() verwenden, um ein Limit von 100 festzulegen, erhalten Sie anfangs nur bis zu 100 onChildAdded()-Callbacks. Wenn in deiner Firebase-Datenbank weniger als 100 Elemente gespeichert sind, wird für jedes Element ein onChildAdded()-Callback ausgelöst.

Wenn sich Artikel ändern, erhalten Sie onChildAdded() Callbacks für Artikel, die in die Abfrage aufgenommen werden, und onChildRemoved() Callbacks für Artikel, die daraus entfernt werden, sodass die Gesamtzahl bei 100 bleibt.

Das folgende Beispiel zeigt, wie in einer Beispiel-Blogging-App eine Abfrage für eine Liste der 100 neuesten Beiträge aller Nutzer abrufen:

Kotlin+KTX

// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys.
databaseReference.child("posts").limitToFirst(100)

Java

// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
Query recentPostsQuery = databaseReference.child("posts")
        .limitToFirst(100);

In diesem Beispiel wird nur eine Abfrage definiert, um die Daten zu synchronisieren, die für die einen angehängten Listener haben.

Nach Schlüssel oder Wert filtern

Sie können startAt(), startAfter(), endAt(), endBefore() und equalTo(), um beliebige Start-, End- und Äquivalenzpunkte für Abfragen. Dies kann beim Paginieren von Daten oder beim Suchen von Elementen mit Kindern nützlich sein. die einen bestimmten Wert haben.

So werden Abfragedaten geordnet

In diesem Abschnitt wird erläutert, wie Daten mithilfe der Sortiermethoden im Klasse Query.

orderByChild

Bei Verwendung von orderByChild() werden Daten, die den angegebenen untergeordneten Schlüssel enthalten, wie folgt sortiert:

  1. Untergeordnete Schlüssel mit dem Wert null für den angegebenen untergeordneten Schlüssel werden .
  2. Untergeordnete Elemente mit dem Wert false für den angegebenen untergeordneten Schlüssel als Nächstes kommen. Wenn mehrere untergeordnete Elemente den Wert false haben, sind sie lexikografisch nach Schlüssel sortiert.
  3. Untergeordnete Elemente mit dem Wert true für den angegebenen untergeordneten Schlüssel als Nächstes kommen. Wenn mehrere untergeordnete Elemente den Wert true haben, sind sie lexikografisch nach Schlüssel sortiert.
  4. Als Nächstes folgen untergeordnete Elemente mit einem numerischen Wert, sortiert in aufsteigender Reihenfolge. Wenn Mehrere untergeordnete Elemente haben denselben numerischen Wert für das angegebene untergeordnete Element werden sie nach Schlüsseln sortiert.
  5. Zeichenfolgen kommen nach Zahlen und werden lexikografisch in aufsteigender Reihenfolge sortiert. Reihenfolge. Wenn mehrere untergeordnete Elemente denselben Wert für das angegebene untergeordnete Element haben lexikografisch nach Schlüssel sortiert.
  6. Objekte kommen zuletzt und werden in aufsteigender Reihenfolge nach Schlüssel sortiert.

orderByKey

Wenn Sie orderByKey() zum Sortieren der Daten verwenden, werden die Daten in aufsteigender Reihenfolge zurückgegeben. nach Taste.

  1. Untergeordnete Elemente mit einem Schlüssel, der als 32-Bit-Ganzzahl geparst werden kann, stehen an erster Stelle, und zwar in aufsteigender Reihenfolge.
  2. Als Nächstes kommen untergeordnete Elemente, deren Schlüssel einen Stringwert enthält. Sie werden lexikografisch in aufsteigender Reihenfolge sortiert.

orderByValue

Bei Verwendung von orderByValue() werden untergeordnete Elemente nach ihrem Wert sortiert. Die Sortierkriterien sind dieselben wie bei orderByChild(), mit der Ausnahme, dass der Wert des Knotens anstelle des Werts eines angegebenen untergeordneten Schlüssels verwendet wird.

Nächste Schritte