Aplikacje Firebase działać, nawet jeśli aplikacja tymczasowo traci połączenie z siecią. Ponadto Firebase dostarcza narzędzi do utrzymującego dane lokalnie, zarządzania obecności i obsługi utajenia.
Trwałość dysku
Firebase aplikacje automatycznie obsłużyć tymczasowe przerwy w działaniu sieci. Buforowane dane są dostępne w trybie offline i Firebase ponownie wysyła żadnych pisze po przywróceniu połączenia z siecią.
Po włączeniu trwałość dysku, aplikacja zapisuje dane lokalnie na urządzeniu, dzięki czemu aplikacja może utrzymać stan w trybie offline, nawet jeśli użytkownik lub system operacyjny uruchamia ponownie aplikację.
Można włączyć trwałość dysku za pomocą tylko jednego wiersza kodu.
Java
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Kotlin+KTX
Firebase.database.setPersistenceEnabled(true)
Trwałość Zachowanie
Poprzez umożliwienie wytrwałości, wszelkie dane, które klient Firebase Realtime Database by zsynchronizować gdy ustąpi internetowych na dysku i jest dostępny w trybie offline, nawet gdy użytkownik lub system operacyjny uruchamia ponownie aplikację. Oznacza to, że aplikacja działa tak, że będzie on-line za pomocą lokalnych danych przechowywanych w pamięci podręcznej. callbacks słuchacz nadal ognia lokalnych aktualizacji.
Klient Firebase Realtime Database automatycznie utrzymuje kolejkę wszystkich operacji zapisu, które są wykonywane w czasie, gdy aplikacja jest w trybie offline. Kiedy wytrwałość jest włączona, to kolejka jest również utrzymywały się na dysku więc wszystkich zapisów są dostępne, gdy użytkownik lub system operacyjny uruchamia ponownie aplikację. Gdy aplikacja odzyskuje łączność, wszystkie operacje są wysyłane do serwera Firebase Realtime Database.
Jeśli aplikacja korzysta z uwierzytelniania Firebase klient Firebase Realtime Baza utrzymuje uwierzytelniania użytkownika tokenu całej ponownym uruchomieniu aplikacji. Jeśli auth tokenu wygasa, gdy aplikacja jest w trybie offline, gdy klient wstrzymuje operacje zapisu aż do swojej aplikacji ponownych uwierzytelnia użytkownika, w przeciwnym razie operacje zapisu może się nie powieść ze względu na zasady bezpieczeństwa.
Utrzymywanie danych Fresh
Firebase Realtime bazy danych synchronizuje i przechowuje lokalną kopię danych dla aktywnych słuchaczy. Ponadto, można zachować określone lokalizacje zsynchronizowane.
Java
DatabaseReference scoresRef = FirebaseDatabase.getInstance().getReference("scores"); scoresRef.keepSynced(true);
Kotlin+KTX
val scoresRef = Firebase.database.getReference("scores") scoresRef.keepSynced(true)
Klient Firebase Realtime Database automatycznie pobiera dane w tych miejscach i utrzymuje ją w synchronizacji nawet jeśli odniesienie ma żadnych aktywnych słuchaczy. Można włączyć synchronizację z powrotem wyłączyć za pomocą następującego wiersza kodu.
Java
scoresRef.keepSynced(false);
Kotlin+KTX
scoresRef.keepSynced(false)
Domyślnie 10MB wcześniej zsynchronizowanych danych jest buforowane. To powinno być wystarczające dla większości zastosowań. Jeśli bufor przerasta skonfigurowaną wielkość, Baza Firebase Realtime czyści dane, które zostały użyte przynajmniej ostatnio. Dane, które są przechowywane w synchronizacji nie jest usuwany z pamięci podręcznej.
Pobierania danych offline
Dane Firebase Realtime baza danych przechowuje wrócił z zapytaniem do użytku w trybie offline. W przypadku pytań skonstruowanych w trybie offline, Baza Firebase Realtime kontynuuje pracę na wcześniej załadowanych danych. Jeżeli żądane dane nie zostały załadowane na Firebase Realtime obciążenia bazy danych z lokalnej pamięci podręcznej. Gdy łączność sieciowa jest ponownie dostępny, ładunki danych i będzie odzwierciedlać zapytania.
Na przykład, ten kod zapytań w ciągu ostatnich czterech pozycji w bazie danych Firebase Realtime partytur
Java
DatabaseReference scoresRef = FirebaseDatabase.getInstance().getReference("scores"); scoresRef.orderByValue().limitToLast(4).addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(@NonNull DataSnapshot snapshot, String previousChild) { Log.d(TAG, "The " + snapshot.getKey() + " dinosaur's score is " + snapshot.getValue()); } // ... });
Kotlin+KTX
val scoresRef = Firebase.database.getReference("scores") scoresRef.orderByValue().limitToLast(4).addChildEventListener(object : ChildEventListener { override fun onChildAdded(snapshot: DataSnapshot, previousChild: String?) { Log.d(TAG, "The ${snapshot.key} dinosaur's score is ${snapshot.value}") } // ... })
Załóżmy, że użytkownik traci połączenie, przechodzi w tryb offline i ponownie uruchamia aplikację. W trybie offline, aplikacja wysyła zapytanie do dwóch ostatnich pozycji z tej samej lokalizacji. To zapytanie zostanie pomyślnie powrócić ostatnie dwie pozycje, ponieważ aplikacja już załadowane wszystkie cztery elementy w kwerendzie powyżej.
Java
scoresRef.orderByValue().limitToLast(2).addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(@NonNull DataSnapshot snapshot, String previousChild) { Log.d(TAG, "The " + snapshot.getKey() + " dinosaur's score is " + snapshot.getValue()); } // ... });
Kotlin+KTX
scoresRef.orderByValue().limitToLast(2).addChildEventListener(object : ChildEventListener { override fun onChildAdded(snapshot: DataSnapshot, previousChild: String?) { Log.d(TAG, "The ${snapshot.key} dinosaur's score is ${snapshot.value}") } // ... })
W poprzednim przykładzie, Firebase Realtime podnosi klienta bazy danych „dziecko dodana” imprezy dla najwyższej punktacji dwóch dinozaurów, używając utrzymywały cache. Ale to nie podniesie zdarzenie „wartość”, ponieważ aplikacja nie została wykonana, że zapytania w trybie online.
Jeśli aplikacja miała zażądać ostatnie sześć pozycji w trybie offline, to get „dziecko” dodaje imprezy dla czterech buforowanych pozycji od razu. Gdy urządzenie powróci do trybu online, klient Firebase Realtime Database synchronizuje się z serwerem i pobiera dwa ostatnie „dziecko dodanej” i „wartości” zdarzenia z aplikacji.
Obsłudze transakcji Offline
Wszelkie transakcje, które są wykonywane podczas gdy aplikacja jest w trybie offline, są ustawiane w kolejce. Gdy odzyskuje łączności sieciowej aplikacji, transakcje są wysyłane do serwera bazy danych w czasie rzeczywistym.
zarządzanie Obecność
W aplikacjach czasu rzeczywistego często jest przydatna do wykrywania kiedy klienci połączyć i rozłączyć. Na przykład, może chcesz oznaczyć użytkownika jako „” w trybie offline, gdy ich rozłącza klienta.
Firebase klienci bazy danych dostarczają prostych prymitywów, które można wykorzystać do zapisu w bazie danych, gdy rozłącza klienta z serwerami Firebase Database. Aktualizacje te występują czy rozłącza klienta czysto czy nie, dzięki czemu można na nich polegać, aby oczyścić dane, nawet jeśli połączenie zostanie upuszczony lub klient wywala. Wszystkie operacje zapisu, w tym ustawieniu, aktualizowania i usuwania, mogą być wykonywane na odłączenie.
Oto prosty przykład zapisu danych po odłączeniu przy użyciu onDisconnect
prymitywne:
Java
DatabaseReference presenceRef = FirebaseDatabase.getInstance().getReference("disconnectmessage"); // Write a string when this client loses connection presenceRef.onDisconnect().setValue("I disconnected!");
Kotlin+KTX
val presenceRef = Firebase.database.getReference("disconnectmessage") // Write a string when this client loses connection presenceRef.onDisconnect().setValue("I disconnected!")
Jak onDisconnect Works
Podczas nawiązywania onDisconnect()
operacji, operacja mieszka na serwerze Firebase Realtime Database. Zabezpieczenie serwer sprawdza, aby upewnić się, że użytkownik może wykonać zdarzenie zapisu wniosek i informuje swoją aplikację, jeżeli jest ona nieważna. Następnie serwer monitoruje połączenia. Jeśli w dowolnym momencie czasy połączeń, lub jest aktywnie zamknięty przez klienta w czasie rzeczywistym danych, bezpieczeństwo Serwer sprawdza po raz drugi (aby upewnić się, że operacja jest nadal ważne), a następnie wywołuje zdarzenie.
Twoja aplikacja może użyć wywołania zwrotnego na operację zapisu w celu zapewnienia onDisconnect
został prawidłowo podłączony:
Java
presenceRef.onDisconnect().removeValue(new DatabaseReference.CompletionListener() { @Override public void onComplete(DatabaseError error, @NonNull DatabaseReference reference) { if (error != null) { Log.d(TAG, "could not establish onDisconnect event:" + error.getMessage()); } } });
Kotlin+KTX
presenceRef.onDisconnect().removeValue { error, reference -> error?.let { Log.d(TAG, "could not establish onDisconnect event: ${error.message}") } }
onDisconnect
zdarzenie może być również anulowana przez wywołanie .cancel()
:
Java
OnDisconnect onDisconnectRef = presenceRef.onDisconnect(); onDisconnectRef.setValue("I disconnected"); // ... // some time later when we change our minds // ... onDisconnectRef.cancel();
Kotlin+KTX
val onDisconnectRef = presenceRef.onDisconnect() onDisconnectRef.setValue("I disconnected") // ... // some time later when we change our minds // ... onDisconnectRef.cancel()
Wykrywanie stanu połączenia
Dla wielu cech obecności związane jest przydatna aplikacja wiedzieć, kiedy jest to online lub offline. Firebase Realtime Database zapewnia specjalną lokalizację na /.info/connected
który jest aktualizowany za każdym razem zmienia stan połączenia bazy danych klienta Firebase czasie rzeczywistym. Oto przykład:
Java
DatabaseReference connectedRef = FirebaseDatabase.getInstance().getReference(".info/connected"); connectedRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { boolean connected = snapshot.getValue(Boolean.class); if (connected) { Log.d(TAG, "connected"); } else { Log.d(TAG, "not connected"); } } @Override public void onCancelled(@NonNull DatabaseError error) { Log.w(TAG, "Listener was cancelled"); } });
Kotlin+KTX
val connectedRef = Firebase.database.getReference(".info/connected") connectedRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val connected = snapshot.getValue(Boolean::class.java) ?: false if (connected) { Log.d(TAG, "connected") } else { Log.d(TAG, "not connected") } } override fun onCancelled(error: DatabaseError) { Log.w(TAG, "Listener was cancelled") } })
/.info/connected
jest wartość logiczna, która nie jest zsynchronizowana między klientami Realtime baz danych, ponieważ wartość jest zależna od stanu klienta. Innymi słowy, jeśli jeden klient czyta /.info/connected
jako fałszywe, to nie ma gwarancji, że oddzielny klient będzie również odczytać fałszywe.
Na Androidzie Firebase automatycznie zarządza stan połączenia zmniejszyć przepustowość i wykorzystanie baterii. Gdy klient ma żadnych aktywnych słuchaczy nie oczekującą pisać lub onDisconnect
operacji, i nie jest wyraźnie odłączony przez goOffline
metodzie Firebase zamyka połączenie po 60 sekundach bezczynności.
Obchodzenie Latency
serwer Sygnatury
Serwery Firebase Realtime Database zapewnić mechanizm wstawiania znaczników czasu generowane na serwerze jako danych. Funkcja ta, w połączeniu z onDisconnect
, zapewnia łatwy sposób wiarygodny zanotuj czas, w którym klient bazy danych w czasie rzeczywistym odłączonym:
Java
DatabaseReference userLastOnlineRef = FirebaseDatabase.getInstance().getReference("users/joe/lastOnline"); userLastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP);
Kotlin+KTX
val userLastOnlineRef = Firebase.database.getReference("users/joe/lastOnline") userLastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP)
Clock Skew
Choć firebase.database.ServerValue.TIMESTAMP
jest znacznie bardziej dokładne i odpowiednie dla większości operacji odczytu / zapisu, może czasami być przydatne do oszacowania zegar klienta skośna w stosunku do serwerów bazy danych w czasie rzeczywistym za Firebase. Można dołączyć wywołania zwrotnego do lokalizacji /.info/serverTimeOffset
aby uzyskać wartość w milisekundach, że klienci Firebase Realtime Database dodać do lokalnego czasu zgłosił (czas epoki w milisekundach), aby oszacować czas serwera. Zauważ, że to przesunięcie na dokładność może mieć wpływ na opóźnienia w sieci, a więc jest przydatny głównie do odkrywania dużych (> 1 sekunda) rozbieżności w czasie zegara.
Java
DatabaseReference offsetRef = FirebaseDatabase.getInstance().getReference(".info/serverTimeOffset"); offsetRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { double offset = snapshot.getValue(Double.class); double estimatedServerTimeMs = System.currentTimeMillis() + offset; } @Override public void onCancelled(@NonNull DatabaseError error) { Log.w(TAG, "Listener was cancelled"); } });
Kotlin+KTX
val offsetRef = Firebase.database.getReference(".info/serverTimeOffset") offsetRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val offset = snapshot.getValue(Double::class.java) ?: 0.0 val estimatedServerTimeMs = System.currentTimeMillis() + offset } override fun onCancelled(error: DatabaseError) { Log.w(TAG, "Listener was cancelled") } })
Sample Obecność App
Łącząc operacje odłączania z monitorujących stan połączenia i serwera znaczników czasu, można zbudować system obecność użytkownika. W tym systemie każdy użytkownik przechowuje dane w miejscu bazy danych, aby wskazać, czy klient Realtime Baza jest online. Klienci ustawić tę lokalizację true gdy przychodzą online i znacznik czasu, kiedy się rozłączyć. Ten znacznik czasu wskazuje czas ostatniej dany użytkownik został Internecie.
Należy pamiętać, że aplikacja powinna kolejce operacji odłączania zanim użytkownik jest oznaczony w trybie online, aby uniknąć warunków wyścigu w przypadku połączenia sieciowego klienta jest stracone, zanim obie komendy mogą być przesyłane do serwera.
Oto prosty system obecność użytkownika:
Java
// Since I can connect from multiple devices, we store each connection instance separately // any time that connectionsRef's value is null (i.e. has no children) I am offline final FirebaseDatabase database = FirebaseDatabase.getInstance(); final DatabaseReference myConnectionsRef = database.getReference("users/joe/connections"); // Stores the timestamp of my last disconnect (the last time I was seen online) final DatabaseReference lastOnlineRef = database.getReference("/users/joe/lastOnline"); final DatabaseReference connectedRef = database.getReference(".info/connected"); connectedRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { boolean connected = snapshot.getValue(Boolean.class); if (connected) { DatabaseReference con = myConnectionsRef.push(); // When this device disconnects, remove it con.onDisconnect().removeValue(); // When I disconnect, update the last time I was seen online lastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP); // Add this device to my connections list // this value could contain info about the device or a timestamp too con.setValue(Boolean.TRUE); } } @Override public void onCancelled(DatabaseError error) { Log.w(TAG, "Listener was cancelled at .info/connected"); } });
Kotlin+KTX
// Since I can connect from multiple devices, we store each connection instance separately // any time that connectionsRef's value is null (i.e. has no children) I am offline val database = Firebase.database val myConnectionsRef = database.getReference("users/joe/connections") // Stores the timestamp of my last disconnect (the last time I was seen online) val lastOnlineRef = database.getReference("/users/joe/lastOnline") val connectedRef = database.getReference(".info/connected") connectedRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val connected = snapshot.getValue<Boolean>() ?: false if (connected) { val con = myConnectionsRef.push() // When this device disconnects, remove it con.onDisconnect().removeValue() // When I disconnect, update the last time I was seen online lastOnlineRef.onDisconnect().setValue(ServerValue.TIMESTAMP) // Add this device to my connections list // this value could contain info about the device or a timestamp too con.setValue(java.lang.Boolean.TRUE) } } override fun onCancelled(error: DatabaseError) { Log.w(TAG, "Listener was cancelled at .info/connected") } })