Pobieranie odwołania do bazy danych
Aby odczytywać dane z bazy danych lub je w niej zapisywać, potrzebujesz instancji DatabaseReference:
DatabaseReference ref = FirebaseDatabase.instance.ref();
Listy do przeczytania i pisania
Dołączanie do listy danych
Aby dołączyć dane do listy w aplikacjach dla wielu użytkowników, użyj metody push().
Metoda push() generuje unikalny klucz za każdym razem, gdy do określonego odwołania Firebase dodawany jest nowy element podrzędny. Dzięki użyciu tych automatycznie generowanych kluczy dla każdego nowego elementu na liście kilku klientów może jednocześnie dodawać elementy podrzędne do tej samej lokalizacji bez konfliktów zapisu. Unikalny klucz generowany przez push() jest oparty na sygnaturze czasowej, więc elementy listy są automatycznie porządkowane chronologicznie.
Możesz użyć odwołania do nowych danych zwróconych przez metodę push(), aby uzyskać wartość automatycznie wygenerowanego klucza elementu podrzędnego lub ustawić dane dla elementu podrzędnego. Właściwość .key odwołania push() zawiera automatycznie wygenerowany klucz.
Możesz użyć tych wygenerowanych automatycznie kluczy, aby uprościć spłaszczanie struktury danych. Więcej informacji znajdziesz w przykładzie rozsyłania danych.
Na przykład push() można użyć do dodania nowego posta do listy postów w aplikacji społecznościowej:
DatabaseReference postListRef = FirebaseDatabase.instance.ref("posts");
DatabaseReference newPostRef = postListRef.push();
newPostRef.set({
// ...
});
Nasłuchiwanie zdarzeń podrzędnych
Zdarzenia podrzędne są wywoływane w odpowiedzi na określone operacje, które mają miejsce w przypadku elementów podrzędnych węzła, np. dodanie nowego elementu podrzędnego za pomocą metody push() lub zaktualizowanie elementu podrzędnego za pomocą metody update().
| Zdarzenie | Typowe wykorzystanie |
|---|---|
onChildAdded |
pobierać listy elementów lub nasłuchiwać dodawania elementów do listy; To zdarzenie jest wywoływane raz dla każdego istniejącego elementu podrzędnego, a następnie za każdym razem, gdy do określonej ścieżki zostanie dodany nowy element podrzędny. Do detektora przekazywany jest zrzut zawierający dane nowego elementu podrzędnego. |
onChildChanged |
Sprawdzanie zmian w elementach na liście. To zdarzenie jest aktywowane za każdym razem, gdy węzeł podrzędny zostanie zmodyfikowany. Obejmuje to wszelkie modyfikacje elementów podrzędnych węzła podrzędnego. Zrzut przekazany do detektora zdarzeń zawiera zaktualizowane dane elementu podrzędnego. |
onChildRemoved |
Nasłuchuj usuwania elementów z listy. To zdarzenie jest wywoływane, gdy usunięte zostanie bezpośrednie dziecko.Zrzut przekazany do bloku wywołania zwrotnego zawiera dane usuniętego dziecka. |
onChildMoved |
nasłuchiwanie zmian kolejności elementów na liście uporządkowanej; Zdarzenia onChildMoved zawsze następują po zdarzeniu onChildChanged, które spowodowało zmianę kolejności elementu (na podstawie bieżącej metody sortowania). |
Każda z tych metod może być przydatna do nasłuchiwania zmian w konkretnym węźle bazy danych. Na przykład aplikacja do blogowania społecznościowego może używać tych metod razem do monitorowania aktywności w komentarzach do posta, jak pokazano poniżej:
final commentsRef = FirebaseDatabase.instance.ref("post-comments/$postId");
commentsRef.onChildAdded.listen((event) {
// A new comment has been added, so add it to the displayed list.
});
commentsRef.onChildChanged.listen((event) {
// A comment has changed; use the key to determine if we are displaying this
// comment and if so displayed the changed comment.
});
commentsRef.onChildRemoved.listen((event) {
// A comment has been removed; use the key to determine if we are displaying
// this comment and if so remove it.
});
Nasłuchiwanie zdarzeń wartości
Chociaż nasłuchiwanie zdarzeń podrzędnych jest zalecanym sposobem odczytywania list danych, w niektórych sytuacjach przydatne jest nasłuchiwanie zdarzeń wartości w odniesieniu do listy.
Dołączenie detektora value do listy danych spowoduje zwrócenie całej listy danych jako pojedynczego zrzutu, który można następnie zapętlić, aby uzyskać dostęp do poszczególnych elementów podrzędnych.
Nawet jeśli zapytanie ma tylko jedno dopasowanie, zrzut nadal jest listą, ale zawiera tylko jeden element. Aby uzyskać dostęp do elementu, musisz wykonać pętlę po wyniku:
myTopPostsQuery.onValue.listen((event) {
for (final child in event.snapshot.children) {
// Handle the post.
}
}, onError: (error) {
// Error.
});
Ten wzorzec może być przydatny, gdy chcesz pobrać wszystkie elementy podrzędne listy w ramach jednej operacji, zamiast nasłuchiwać dodatkowych zdarzeń dodania elementu podrzędnego.
Sortowanie i filtrowanie danych
Możesz użyć klasy Query, aby pobrać dane posortowane według klucza, wartości lub wartości elementu podrzędnego. Możesz też filtrować posortowane wyniki, aby uzyskać określoną liczbę wyników lub zakres kluczy bądź wartości.
Sortowanie danych
Aby pobrać posortowane dane, zacznij od określenia jednej z metod sortowania, aby określić, jak mają być uporządkowane wyniki:
| Metoda | Wykorzystanie |
|---|---|
orderByChild() |
Porządkuj wyniki według wartości określonego klucza podrzędnego lub zagnieżdżonej ścieżki podrzędnej. |
orderByKey() |
Porządkowanie wyników według kluczy podrzędnych. |
orderByValue() |
Porządkowanie wyników według wartości podrzędnych. |
Możesz używać tylko jednej metody sortowania naraz. Wielokrotne wywołanie metody sortowania w tym samym zapytaniu powoduje błąd.
Poniższy przykład pokazuje, jak pobrać listę najpopularniejszych postów użytkownika posortowanych według liczby gwiazdek:
final myUserId = FirebaseAuth.instance.currentUser?.uid;
final topUserPostsRef = FirebaseDatabase.instance
.ref("user-posts/$myUserId")
.orderByChild("starCount");
Definiuje zapytanie, które w połączeniu z detektorem podrzędnym synchronizuje klienta z postami użytkownika ze ścieżki w bazie danych na podstawie jego identyfikatora użytkownika, uporządkowanymi według liczby gwiazdek, które otrzymał każdy post. Ta technika używania identyfikatorów jako kluczy indeksu jest nazywana rozgałęzieniem danych. Więcej informacji na ten temat znajdziesz w artykule Struktura bazy danych.
Wywołanie metody orderByChild() określa klucz podrzędny, według którego mają być sortowane wyniki. W tym przypadku posty są sortowane według wartości ich elementu podrzędnego "starCount". Zapytania można też porządkować według zagnieżdżonych elementów podrzędnych, jeśli masz dane, które wyglądają tak:
"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 przypadku możemy uporządkować elementy listy według wartości zagnieżdżonych pod kluczem metrics, określając ścieżkę względną do zagnieżdżonego elementu podrzędnego w wywołaniu orderByChild().
final mostViewedPosts =
FirebaseDatabase.instance.ref('posts').orderByChild('metrics/views');
Więcej informacji o porządkowaniu innych typów danych znajdziesz w artykule Jak są porządkowane dane zapytań.
Filtrowanie danych
Aby filtrować dane, podczas tworzenia zapytania możesz połączyć dowolną metodę limitu lub zakresu z metodą sortowania.
| Metoda | Wykorzystanie |
|---|---|
limitToFirst() |
Określa maksymalną liczbę elementów do zwrócenia od początku listy uporządkowanej wyników. |
limitToLast() |
Ustawia maksymalną liczbę elementów do zwrócenia z końca uporządkowanej listy wyników. |
startAt() |
Zwraca elementy o wartości większej niż określony klucz lub wartość albo równej im, 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 niż lub równe określonemu kluczowi lub określonej 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 wartości, w zależności od wybranej metody sortowania. |
W przeciwieństwie do metod sortowania możesz łączyć wiele funkcji limitu lub zakresu.
Możesz na przykład połączyć metody startAt() i endAt(), aby ograniczyć wyniki do określonego zakresu wartości.
Ograniczanie liczby wyników
Możesz użyć metod limitToFirst() i limitToLast(), aby ustawić maksymalną liczbę dzieci, które mają być synchronizowane w przypadku danego zdarzenia. Jeśli na przykład użyjesz limitToFirst(), aby ustawić limit na 100, początkowo otrzymasz tylko maksymalnie 100 zdarzeń onChildAdded. Jeśli w bazie danych Firebase masz mniej niż 100 elementów, dla każdego z nich wywoływane jest zdarzenie onChildAdded.
W miarę zmian elementów otrzymujesz zdarzenia onChildAdded dotyczące elementów, które zaczynają spełniać warunki zapytania, oraz zdarzenia onChildRemoved dotyczące elementów, które przestają je spełniać, dzięki czemu łączna liczba elementów pozostaje na poziomie 100.
Poniższy przykład pokazuje, jak przykładowa aplikacja do blogowania definiuje zapytanie, aby pobrać listę 100 najnowszych postów wszystkich użytkowników:
final recentPostsRef = FirebaseDatabase.instance.ref('posts').limitToLast(100);
Ten przykład definiuje tylko zapytanie. Aby faktycznie zsynchronizować dane, musi mieć dołączony detektor.
Filtruj według klucza lub wartości
Możesz użyć startAt(), startAfter(), endAt(), endBefore() i equalTo(), aby wybrać dowolne punkty początkowe, końcowe i równoważne dla zapytań. Może to być przydatne do dzielenia danych na strony lub znajdowania elementów z elementami podrzędnymi o określonej wartości.
Jak są uporządkowane dane z zapytań
W tej sekcji wyjaśniamy, jak dane są sortowane według poszczególnych metod sortowania w klasie Query.
orderByChild
Gdy używasz orderByChild(), dane zawierające określony klucz podrzędny są porządkowane w ten sposób:
- Dzieci z wartością
nulldla określonego klucza podrzędnego są wyświetlane jako pierwsze. - Następnie wyświetlane są elementy podrzędne z wartością
falsedla określonego klucza podrzędnego. Jeśli wiele elementów podrzędnych ma wartośćfalse, są one sortowane leksykograficznie według klucza. - Następnie wyświetlane są elementy podrzędne z wartością
truedla określonego klucza podrzędnego. Jeśli wiele elementów podrzędnych ma wartośćtrue, są one sortowane leksykograficznie według klucza. - Następnie wyświetlane 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ą dla określonego węzła podrzędnego, są one sortowane według klucza.
- Ciągi znaków występują po liczbach i są sortowane leksykograficznie w kolejności rosnącej. Jeśli wiele elementów podrzędnych ma tę samą wartość dla określonego węzła podrzędnego, są one uporządkowane leksykograficznie według klucza.
- Obiekty są na końcu i są sortowane leksykograficznie według klucza w kolejności rosnącej.
orderByKey
Gdy używasz orderByKey() do sortowania danych, są one zwracane w kolejności rosnącej według klucza.
- Najpierw wyświetlane są elementy podrzędne z kluczem, który można przeanalizować jako 32-bitową liczbę całkowitą, posortowane w kolejności rosnącej.
- Następnie wyświetlane są elementy podrzędne z wartością ciągu znaków jako kluczem, posortowane leksykograficznie w porządku rosnącym.
orderByValue
Gdy używasz orderByValue(), elementy podrzędne są uporządkowane według wartości. Kryteria sortowania są takie same jak w przypadku orderByChild(), ale zamiast wartości określonego klucza podrzędnego używana jest wartość węzła.
Odłączanie detektorów
Wywołania zwrotne są usuwane przez wywołanie metody off() w odwołaniu do bazy danych Firebase.
Możesz usunąć pojedynczy obiekt nasłuchujący, przekazując go jako parametr do off().
Wywołanie metody off() w lokalizacji bez argumentów powoduje usunięcie wszystkich detektorów w tej lokalizacji.
Wywołanie metody off() na obiekcie nasłuchującym nadrzędnym nie powoduje automatycznego usunięcia obiektów nasłuchujących zarejestrowanych w jego węzłach podrzędnych. Aby usunąć wywołanie zwrotne, należy wywołać metodę off() również na wszystkich obiektach nasłuchujących podrzędnych.