Praca z listami danych na Androidzie

Ten dokument dotyczy pracy z listami danych w Firebase. Aby poznać podstawy odczytywania i zapisywania danych Firebase. Odczyt i zapis danych na Androidzie

Pobieranie odniesienia do bazy danych

Aby móc odczytywać i zapisywać dane z bazy danych, potrzebujesz instancji DatabaseReference:

Kotlin+KTX

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

Java

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

Odczytywanie i zapisywanie list

Dołącz do listy danych

Użyj metody push(), aby dołączać dane do listy w aplikacjach, które mają wielu użytkowników. Metoda push() generuje unikalny klucz przy każdym nowym kluczu element podrzędny został dodany do określonego odwołania Firebase. Za pomocą tych generowanych automatycznie kluczy dla każdego nowego elementu na liście, kilka klientów może dodawanie dzieci w tym samym czasie do tej samej lokalizacji bez konfliktów zapisu. unikalny klucz generowany przez usługę push() jest oparty na sygnaturze czasowej, więc elementy listy są automatycznie uporządkowane chronologicznie.

Możesz użyć odwołania do nowych danych zwróconych przez metodę push(), aby uzyskać wartość automatycznie wygenerowanego klucza lub zbioru danych wydawcy podrzędnego. Łączę Funkcja getKey() w pliku referencyjnym push() zwraca wartość argumentu automatycznie wygenerowanego klucza.

Możesz użyć tych automatycznie wygenerowanych kluczy, aby uprościć udostępnianie danych do jego struktury. Więcej informacji znajdziesz w opisie rozpowszechniania danych przykład.

Nasłuchuj zdarzeń podrzędnych

Podczas pracy z listami aplikacja powinna nasłuchiwać zdarzeń podrzędnych a nie wartości używanych dla pojedynczych obiektów.

Zdarzenia podrzędne są wywoływane w reakcji na określone operacje elementu podrzędnego węzła pochodzącego z operacji, takiej jak nowy element podrzędny dodany za pomocą funkcji push() lub element podrzędny aktualizowany za pomocą metody updateChildren(). Każdy z tych elementów może być przydatny do nasłuchiwania zmian w konkretnym węźle w bazie danych.

Aby nasłuchiwać zdarzeń podrzędnych z DatabaseReference, dołącz plik ChildEventListener:

Detektor Wywołanie zwrotne zdarzenia Typowe zastosowanie
ChildEventListener onChildAdded() Pobieranie list elementów lub słuchanie, czy dodano elementy do listy. To wywołanie zwrotne jest wywoływane raz dla każdego istniejącego elementu podrzędnego, a następnie ponownie za każdym razem, gdy do określonej ścieżki jest dodawany nowy element podrzędny. Pole DataSnapshot przekazane do detektora zawiera dane nowego dziecka.
onChildChanged() Wykrywaj zmiany wprowadzone w elementach na liście. To zdarzenie było wywoływane za każdym razem, gdy węzeł podrzędny został zmodyfikowany, w tym wszelkie modyfikacje elementów potomnych do węzła podrzędnego. Element DataSnapshot został przekazany do zdarzenia detektor zawiera zaktualizowane dane elementu podrzędnego.
onChildRemoved() Nasłuchuj elementów usuwanych z listy. Pole DataSnapshot przekazane do wywołania zwrotnego zdarzenia zawiera parametr dotyczące usuniętego konta podrzędnego.
onChildMoved() Wykrywaj zmiany kolejności elementów na liście uporządkowanej. To zdarzenie jest wywoływane za każdym razem, gdy onChildChanged() wywołanie zwrotne jest wywoływane przez aktualizację, która powoduje zmianę kolejności elementu podrzędnego. Jest używany z danymi uporządkowanych według: orderByChild lub orderByValue.

Na przykład aplikacja do obsługi blogów społecznościowych może wykorzystywać te metody aby monitorować aktywność w komentarzach do posta, na przykład:

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

Wykrywaj zdarzenia dotyczące wartości

Podczas korzystania z funkcji ChildEventListener zalecany sposób odczytywania list , zdarzają się sytuacje, w których dołączanie elementu ValueEventListener do listy jest przydatny.

Dołączanie atrybutu ValueEventListener do listy danych spowoduje zwrócenie całej danych jako pojedynczego elementu DataSnapshot, który można następnie odtworzyć w formie pętli dostępu do poszczególnych dzieci.

Nawet jeśli dla zapytania znaleziono tylko jedno dopasowanie, zrzut nadal jest lista; zawiera tylko jeden element. Aby uzyskać dostęp do elementu, musisz utworzyć pętlę w stosunku do wyniku:

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

Ten wzorzec może być przydatny, gdy chcesz pobrać wszystkie elementy podrzędne listy w jednej operacji, zamiast nasłuchiwać dodatkowych onChildAdded zdarzeń.

Odłącz detektory

Wywołania zwrotne są usuwane przez wywołanie metody removeEventListener() na Twoim Dokumentacja bazy danych Firebase.

Jeśli detektor został dodany wiele razy do lokalizacji danych, jest wywoływane wiele razy dla każdego zdarzenia i musisz odłączyć je tę samą liczbę aby ją całkowicie usunąć.

Wywoływanie połączenia removeEventListener() w przypadku detektora nadrzędnego automatycznie usuwać detektory zarejestrowane w węzłach podrzędnych; Funkcja removeEventListener() musi być również wywoływana w przypadku podrzędnych detektorów , aby usunąć wywołanie zwrotne.

Sortowanie i filtrowanie danych

Możesz użyć klasy Query Bazy danych czasu rzeczywistego, aby pobrać dane posortowane według według klucza, wartości lub wartości elementu podrzędnego. Możesz też filtrować posortowany wynik do określonej liczby wyników lub zakresu kluczy albo .

Sortowanie danych

Aby pobrać posortowane dane, zacznij od określenia jednej z metod Określanie kolejności wyników:

Metoda Wykorzystanie
orderByChild() Uporządkuj wyniki według wartości określonego klucza podrzędnego lub zagnieżdżonej ścieżki podrzędnej.
orderByKey() Uporządkuj wyniki według kluczy podrzędnych.
orderByValue() Uporządkuj wyniki według wartości podrzędnych.

W danym momencie możesz używać tylko jednej metody sortowania. Wywoływanie kolejności według metody które kilka razy wywoła to samo zapytanie, spowoduje zgłoszenie błędu.

Poniższy przykład pokazuje, jak można pobrać listę danych użytkownika najpopularniejsze posty posortowane według liczby gwiazdek:

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

Definiuje zapytanie, które w połączeniu z detektorem podrzędnym synchronizuje klienta z postami użytkownika ze ścieżki w bazie danych. według identyfikatora użytkownika, uporządkowanych według liczby gwiazdek przyznanych poszczególnym postom. Ta technika wykorzystywania identyfikatorów jako kluczy indeksu nosi nazwę rozpowszechniania danych. Możesz odczytać więcej na ten temat znajdziesz w Utwórz strukturę bazy danych.

Wywołanie metody orderByChild() określa klucz podrzędny, aby uporządkować według. W takim przypadku posty są sortowane według wartości "starCount" dziecko. Zapytania mogą być też porządkowane według zagnieżdżonych dzieci, w przypadku gdy masz dane podobne do tych:

"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",
  }
},

W tym przykładzie możemy uporządkować elementy listy według wartości zagnieżdżonych w metrics, określając ścieżkę względną do zagnieżdżonego elementu podrzędnego w naszym orderByChild() połączenie.

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

Więcej informacji o kolejności innych typów danych znajdziesz na stronie Jak jest ustalana kolejność danych w zapytaniach.

Filtrowanie danych

Aby filtrować dane, możesz połączyć dowolne metody limitów lub zakresów za pomocą funkcji kolejność według metody podczas tworzenia zapytania.

Metoda Wykorzystanie
limitToFirst() Określa maksymalną liczbę elementów do zwrócenia od początku wartości uporządkowana lista wyników.
limitToLast() Określa maksymalną liczbę produktów do zwrócenia od końca zamówionego produktu z listą wyników.
startAt() Zwraca elementy większe lub równe określonemu kluczowi lub wartościowi w zależności od wybranej metody sortowania.
startAfter() Zwraca elementy większe niż określony klucz lub wartość w zależności od wybranej metody sortowania.
endAt() Zwraca elementy mniejsze lub równe podanej wartości klucza bądź wartości w zależności od wybranej metody sortowania.
endBefore() Zwraca elementy mniejsze niż określony klucz lub wartość w zależności od wybranej metody sortowania.
equalTo() Zwraca elementy równe określonemu kluczowi lub określonej wartości w zależności od wybranej metody sortowania.

W przeciwieństwie do metod sortowania według kolejności można łączyć wiele funkcji ograniczeń lub zakresu. Możesz na przykład połączyć metody startAt() i endAt(), aby ograniczyć wyniki do określonego zakresu wartości.

Nawet jeśli dla zapytania znaleziono tylko jedno dopasowanie, zrzut nie zmienia się listę; zawiera tylko jeden element. Aby uzyskać dostęp do elementu, musisz mieć zapętlanie wyniku:

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

Ogranicz liczbę wyników

Możesz użyć metod limitToFirst() i limitToLast(), aby ustawić maksymalna liczba dzieci do zsynchronizowania w przypadku danego wywołania zwrotnego. Na przykład, jeśli używasz aplikacji limitToFirst(), aby ustawić limit wynoszący 100, początkowo otrzymasz tylko do 100 wywołań zwrotnych onChildAdded(). Jeśli na bazy danych Firebase, dla każdego elementu uruchamia się wywołanie zwrotne onChildAdded().

W miarę zmiany elementów otrzymujesz onChildAdded() wywołań zwrotnych dla elementów, które zostały wprowadzone oraz wywołania zwrotne onChildRemoved() dla elementów, które z niego opuszczają, tak aby łączna liczba pozostaje na poziomie 100.

Poniższy przykład pokazuje, jak przykładowa aplikacja do blogowania definiuje zapytanie w celu pobierz listę 100 najnowszych postów wszystkich użytkowników:

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

Ten przykład definiuje tylko zapytanie służące do faktycznego synchronizowania danych, których potrzebuje ma dołączonego detektora.

Filtruj według klucza lub wartości

Możesz używać tych usług: startAt(), startAfter(), endAt(), endBefore() i equalTo(), aby wybrać dowolny punkt początkowy, końcowy i równoważny dla zapytań. Może to być przydatne przy dzieleniu danych na strony lub znajdowaniu elementów mających dzieci które mają określoną wartość.

Sposób porządkowania danych zapytań

W tej sekcji omówiono sposób sortowania danych według poszczególnych metod Query zajęcia.

orderByChild

Gdy używasz orderByChild(), dane zawierające określony klucz podrzędny są w następującej kolejności:

  1. Elementy podrzędne z wartością null określonego klucza podrzędnego są dostarczane .
  2. Elementy podrzędne o wartości false określonego klucza podrzędnego co dalej. Jeśli kilka elementów podrzędnych ma wartość false, są one posortowane leksykograficznie według klucza.
  3. Elementy podrzędne o wartości true określonego klucza podrzędnego co dalej. Jeśli kilka elementów podrzędnych ma wartość true, są one posortowane leksykograficznie według klucza.
  4. Następne są elementy podrzędne z wartością liczbową, posortowane w kolejności rosnącej. Jeśli kilka elementów podrzędnych ma tę samą wartość liczbową określonego elementu podrzędnego węzłów, są one sortowane według klucza.
  5. Ciągi znaków znajdują się po liczbach i są sortowane leksykograficznie w kolejności rosnącej zamówienie. Jeśli kilka elementów podrzędnych ma tę samą wartość określonego elementu podrzędnego są uporządkowane leksykograficznie według klucza.
  6. Obiekty są na końcu i są sortowane leksykograficznie według klucza w kolejności rosnącej.

orderByKey

Gdy dane są sortowane przy użyciu funkcji orderByKey(), są one zwracane w kolejności rosnącej klawiszem.

  1. Elementy podrzędne z kluczem, który można przeanalizować jako 32-bitową liczbę całkowitą, są na pierwszym miejscu, posortowane w kolejności rosnącej.
  2. Następnym elementem są elementy podrzędne z wartością w postaci ciągu znaków, posortowane leksykograficznie w kolejności rosnącej.

orderByValue

Gdy używasz metody orderByValue(), elementy podrzędne są uporządkowane według wartości. Kolejność kryteria są takie same jak w orderByChild(), z wyjątkiem wartości węzła zamiast wartości określonego klucza podrzędnego.

Dalsze kroki