Cloud Firestore unterstützt Offline-Datenpersistenz. Diese Funktion speichert eine Kopie der Cloud Firestore-Daten, die Ihre App aktiv verwendet, zwischen, sodass Ihre App auf die Daten zugreifen kann, wenn das Gerät offline ist. Sie können die zwischengespeicherten Daten schreiben, lesen, anhören und abfragen. Wenn das Gerät wieder online ist, synchronisiert Cloud Firestore alle lokalen Änderungen, die von Ihrer App vorgenommen wurden, mit dem Cloud Firestore-Back-End.
Um die Offline-Persistenz zu verwenden, müssen Sie keine Änderungen an dem Code vornehmen, den Sie für den Zugriff auf Cloud Firestore-Daten verwenden. Bei aktivierter Offline-Persistenz verwaltet die Cloud Firestore-Clientbibliothek automatisch den Online- und Offline-Datenzugriff und synchronisiert lokale Daten, wenn das Gerät wieder online ist.
Offline-Persistenz konfigurieren
Wenn Sie Cloud Firestore initialisieren, können Sie die Offline-Persistenz aktivieren oder deaktivieren:
- Für Android- und Apple-Plattformen ist die Offline-Persistenz standardmäßig aktiviert. Um die Persistenz zu deaktivieren, setzen Sie die Option
PersistenceEnabled
auffalse
. - Für das Web ist die Offline-Persistenz standardmäßig deaktiviert. Um Persistenz zu aktivieren, rufen Sie die
enablePersistence
Methode auf. Der Cache von Cloud Firestore wird zwischen Sitzungen nicht automatisch geleert. Wenn Ihre Web-App vertrauliche Informationen verarbeitet, sollten Sie daher den Benutzer fragen, ob er sich auf einem vertrauenswürdigen Gerät befindet, bevor Sie die Persistenz aktivieren.
Web version 9
import { enableIndexedDbPersistence } from "firebase/firestore"; enableIndexedDbPersistence(db) .catch((err) => { if (err.code == 'failed-precondition') { // Multiple tabs open, persistence can only be enabled // in one tab at a a time. // ... } else if (err.code == 'unimplemented') { // The current browser does not support all of the // features required to enable persistence // ... } }); // Subsequent queries will use persistence, if it was enabled successfully
Web version 8
firebase.firestore().enablePersistence() .catch((err) => { if (err.code == 'failed-precondition') { // Multiple tabs open, persistence can only be enabled // in one tab at a a time. // ... } else if (err.code == 'unimplemented') { // The current browser does not support all of the // features required to enable persistence // ... } }); // Subsequent queries will use persistence, if it was enabled successfully
Schnell
let settings = FirestoreSettings() settings.isPersistenceEnabled = true // Any additional options // ... // Enable offline data persistence let db = Firestore.firestore() db.settings = settings
Ziel c
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init]; settings.persistenceEnabled = YES; // Any additional options // ... // Enable offline data persistence FIRFirestore *db = [FIRFirestore firestore]; db.settings = settings;
Kotlin+KTX
val settings = firestoreSettings { isPersistenceEnabled = true } db.firestoreSettings = settings
Java
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder() .setPersistenceEnabled(true) .build(); db.setFirestoreSettings(settings);
Dart
// Apple and Android db.settings = const Settings(persistenceEnabled: true); // Web await db .enablePersistence(const PersistenceSettings(synchronizeTabs: true));
Cache-Größe konfigurieren
Wenn Persistenz aktiviert ist, speichert Cloud Firestore jedes vom Back-End empfangene Dokument für den Offline-Zugriff im Cache. Cloud Firestore legt einen Standardschwellenwert für die Cache-Größe fest. Nachdem der Standardwert überschritten wurde, versucht Cloud Firestore regelmäßig, ältere, nicht verwendete Dokumente zu bereinigen. Sie können einen anderen Schwellenwert für die Cache-Größe konfigurieren oder den Bereinigungsprozess vollständig deaktivieren:
Web version 9
import { initializeFirestore, CACHE_SIZE_UNLIMITED } from "firebase/firestore"; const firestoreDb = initializeFirestore(app, { cacheSizeBytes: CACHE_SIZE_UNLIMITED });
Web version 8
firebase.firestore().settings({ cacheSizeBytes: firebase.firestore.CACHE_SIZE_UNLIMITED });
Schnell
// The default cache size threshold is 100 MB. Configure "cacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "FirestoreCacheSizeUnlimited" // to disable clean-up. let settings = Firestore.firestore().settings settings.cacheSizeBytes = FirestoreCacheSizeUnlimited Firestore.firestore().settings = settings
Ziel c
// The default cache size threshold is 100 MB. Configure "cacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "kFIRFirestoreCacheSizeUnlimited" // to disable clean-up. FIRFirestoreSettings *settings = [FIRFirestore firestore].settings; settings.cacheSizeBytes = kFIRFirestoreCacheSizeUnlimited; [FIRFirestore firestore].settings = settings;
Kotlin+KTX
// The default cache size threshold is 100 MB. Configure "setCacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED" // to disable clean-up. val settings = FirebaseFirestoreSettings.Builder() .setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED) .build() db.firestoreSettings = settings
Java
// The default cache size threshold is 100 MB. Configure "setCacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED" // to disable clean-up. FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder() .setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED) .build(); db.setFirestoreSettings(settings);
Dart
db.settings = const Settings( persistenceEnabled: true, cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED, );
Offline-Daten anhören
Während das Gerät offline ist und Sie die Offline-Persistenz aktiviert haben, erhalten Ihre Listener Listen-Ereignisse, wenn sich die lokal zwischengespeicherten Daten ändern. Sie können Dokumente, Sammlungen und Abfragen anhören.
Um zu überprüfen, ob Sie Daten vom Server oder vom Cache empfangen, verwenden Sie die fromCache
Eigenschaft für SnapshotMetadata
in Ihrem Snapshot-Ereignis. Wenn fromCache
true
ist, stammen die Daten aus dem Cache und sind möglicherweise veraltet oder unvollständig. Wenn fromCache
false
ist, sind die Daten vollständig und aktuell mit den neuesten Updates auf dem Server.
Standardmäßig wird kein Ereignis ausgelöst, wenn sich nur die SnapshotMetadata
geändert haben. Wenn Sie sich auf die fromCache
Werte verlassen, geben Sie die listen-Option includeMetadataChanges
an, wenn Sie Ihren Listen-Handler anhängen.
Web version 9
import { collection, onSnapshot, where, query } from "firebase/firestore"; const q = query(collection(db, "cities"), where("state", "==", "CA")); onSnapshot(q, { includeMetadataChanges: true }, (snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } const source = snapshot.metadata.fromCache ? "local cache" : "server"; console.log("Data came from " + source); }); });
Web version 8
db.collection("cities").where("state", "==", "CA") .onSnapshot({ includeMetadataChanges: true }, (snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } var source = snapshot.metadata.fromCache ? "local cache" : "server"; console.log("Data came from " + source); }); });
Schnell
// Listen to metadata updates to receive a server snapshot even if // the data is the same as the cached data. db.collection("cities").whereField("state", isEqualTo: "CA") .addSnapshotListener(includeMetadataChanges: true) { querySnapshot, error in guard let snapshot = querySnapshot else { print("Error retreiving snapshot: \(error!)") return } for diff in snapshot.documentChanges { if diff.type == .added { print("New city: \(diff.document.data())") } } let source = snapshot.metadata.isFromCache ? "local cache" : "server" print("Metadata: Data fetched from \(source)") }
Ziel c
// Listen to metadata updates to receive a server snapshot even if // the data is the same as the cached data. [[[db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"] addSnapshotListenerWithIncludeMetadataChanges:YES listener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error retreiving snapshot: %@", error); return; } for (FIRDocumentChange *diff in snapshot.documentChanges) { if (diff.type == FIRDocumentChangeTypeAdded) { NSLog(@"New city: %@", diff.document.data); } } NSString *source = snapshot.metadata.isFromCache ? @"local cache" : @"server"; NSLog(@"Metadata: Data fetched from %@", source); }];
Kotlin+KTX
db.collection("cities").whereEqualTo("state", "CA") .addSnapshotListener(MetadataChanges.INCLUDE) { querySnapshot, e -> if (e != null) { Log.w(TAG, "Listen error", e) return@addSnapshotListener } for (change in querySnapshot!!.documentChanges) { if (change.type == DocumentChange.Type.ADDED) { Log.d(TAG, "New city: ${change.document.data}") } val source = if (querySnapshot.metadata.isFromCache) "local cache" else "server" Log.d(TAG, "Data fetched from $source") } }
Java
db.collection("cities").whereEqualTo("state", "CA") .addSnapshotListener(MetadataChanges.INCLUDE, new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot querySnapshot, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen error", e); return; } for (DocumentChange change : querySnapshot.getDocumentChanges()) { if (change.getType() == Type.ADDED) { Log.d(TAG, "New city:" + change.getDocument().getData()); } String source = querySnapshot.getMetadata().isFromCache() ? "local cache" : "server"; Log.d(TAG, "Data fetched from " + source); } } });
Dart
db .collection("cities") .where("state", isEqualTo: "CA") .snapshots(includeMetadataChanges: true) .listen((querySnapshot) { for (var change in querySnapshot.docChanges) { if (change.type == DocumentChangeType.added) { final source = (querySnapshot.metadata.isFromCache) ? "local cache" : "server"; print("Data fetched from $source}"); } } });
Holen Sie sich Offline-Daten
Wenn Sie ein Dokument erhalten, während das Gerät offline ist, gibt Cloud Firestore Daten aus dem Cache zurück.
Beim Abfragen einer Sammlung wird ein leeres Ergebnis zurückgegeben, wenn keine zwischengespeicherten Dokumente vorhanden sind. Beim Abrufen eines bestimmten Dokuments wird stattdessen ein Fehler zurückgegeben.
Offline-Daten abfragen
Die Abfrage funktioniert mit Offline-Persistenz. Sie können die Ergebnisse von Abfragen entweder mit einem direkten Abruf oder durch Zuhören abrufen, wie in den vorherigen Abschnitten beschrieben. Sie können auch neue Abfragen für lokal gespeicherte Daten erstellen, während das Gerät offline ist, aber die Abfragen werden zunächst nur für die zwischengespeicherten Dokumente ausgeführt.
Konfigurieren Sie Offline-Abfrageindizes
Standardmäßig scannt das Firestore SDK alle Dokumente in einer Sammlung in seinem lokalen Cache, wenn Offline-Abfragen ausgeführt werden. Bei diesem Standardverhalten kann die Offline-Abfrageleistung leiden, wenn Benutzer längere Zeit offline sind.
Sie können die Leistung von Offline-Abfragen verbessern, indem Sie lokale Abfrageindizes konfigurieren:
Schnell
Das Apple-Plattform-SDK stellt eine setIndexConfiguration
Methode bereit, die dieselbe JSON-strukturierte Konfiguration liest, die zum Konfigurieren von Indizes auf dem Server verwendet wird, wobei dasselbe Indexdefinitionsformat verwendet wird.
// You will normally read this from a file asset or cloud storage. let indexConfigJson = """ { indexes: [ ... ], fieldOverrides: [ ... ] } """ // Apply the configuration. Firestore.firestore().setIndexConfiguration(indexConfigJson)
Ziel c
Das Apple-Plattform-SDK stellt setIndexConfiguration
- Methoden bereit, die dieselbe JSON-strukturierte Konfiguration lesen, die zum Konfigurieren von Indizes auf dem Server verwendet wird, wobei dasselbe Indexdefinitionsformat verwendet wird.
// You will normally read this from a file asset or cloud storage. NSString *indexConfigJson = @" { " " indexes: [ " " ... " " ], " " fieldOverrides: [ " " ... " " ] " " } "; // Apply the configuration. [[FIRFirestore firestore] setIndexConfigurationFromJSON:indexConfigJson completion:^(NSError * _Nullable error) { // ... }];
Java
Das Android SDK stellt eine setIndexConfiguration
Methode bereit, die dieselbe JSON-strukturierte Konfiguration liest, die zum Konfigurieren von Indizes auf dem Server verwendet wird, wobei dasselbe Indexdefinitionsformat verwendet wird.
// You will normally read this from a file asset or cloud storage. String indexConfigJson = " { " + " indexes: [ " + " ... " + " ], " + " fieldOverrides: [ " + " ... " + " ] " + " } "; // Apply the configuration. FirebaseFirestore.getInstance().setIndexConfiguration(indexConfigJson);
Kotlin+KTX
Das Android SDK stellt eine setIndexConfiguration
Methode bereit, die dieselbe JSON-strukturierte Konfiguration liest, die zum Konfigurieren von Indizes auf dem Server verwendet wird, wobei dasselbe Indexdefinitionsformat verwendet wird.
// You will normally read this from a file asset or cloud storage. val indexConfigJson = """ { indexes: [ ... ], fieldOverrides: [ ... ] } """ // Apply the configuration. FirebaseFirestore.getInstance().setIndexConfiguration(indexConfigJson)
Dart
Das Flutter-SDK stellt eine setIndexConfigurationFromJSON
-Methode bereit, die dieselbe JSON-strukturierte Konfiguration liest, die zum Konfigurieren von Indizes auf dem Server verwendet wird, und dabei demselben Indexdefinitionsformat folgt.
// You will normally read this from a file asset or cloud storage. var indexConfigJson = """ { indexes: [ ... ], fieldOverrides: [ ... ] } """; // Apply the configuration. await FirebaseFirestore.instance.setIndexConfigurationFromJSON(json: indexConfigJson);
Alternativ können Sie die Methode setIndexConfiguration
verwenden, um Indizes mit einer klassenbasierten API zu konfigurieren.
var indexes = [ Index( collectionGroup: "posts", queryScope: QueryScope.collection, fields: [ IndexField(fieldPath: "author", arrayConfig: ArrayConfig.contains), IndexField(fieldPath: "timestamp", order: Order.descending) ], ), ]; await FirebaseFirestore.instance.setIndexConfiguration(indexes: indexes);
Die zu verwendende Offline-Indexkonfiguration hängt davon ab, auf welche Sammlungen und Dokumente Ihre App häufig offline zugreift und von der gewünschten Offline-Leistung. Während Sie Ihre Back-End-Indexkonfiguration für die Verwendung auf dem Client exportieren können, unterscheiden sich die Offline-Zugriffsmuster Ihrer App wahrscheinlich erheblich von den Online-Zugriffsmustern, sodass Ihre Online-Indexkonfiguration möglicherweise nicht für die Offline-Verwendung geeignet ist. Auf welche Sammlungen und Dokumente soll Ihre App performant offline zugreifen? Nachdem Sie das Verhalten Ihrer App analysiert haben, befolgen Sie die Prinzipien für die Indexdefinition aus dem Indexierungsleitfaden .
So machen Sie Offline-Indexkonfigurationen zum Laden in Ihrer Client-App verfügbar:
- kompilieren und verteilen Sie sie mit Ihrer App
- Laden Sie sie von einem CDN herunter
- Rufen Sie sie von einem Speichersystem wie Cloud Storage for Firebase ab.
Deaktivieren und aktivieren Sie den Netzwerkzugriff
Sie können die folgende Methode verwenden, um den Netzwerkzugriff für Ihren Cloud Firestore-Client zu deaktivieren. Während der Netzwerkzugriff deaktiviert ist, rufen alle Snapshot-Listener und Dokumentanforderungen Ergebnisse aus dem Cache ab. Schreibvorgänge werden in die Warteschlange gestellt, bis der Netzwerkzugriff wieder aktiviert wird.
Web version 9
import { disableNetwork } from "firebase/firestore"; await disableNetwork(db); console.log("Network disabled!"); // Do offline actions // ...
Web version 8
firebase.firestore().disableNetwork() .then(() => { // Do offline actions // ... });
Schnell
Firestore.firestore().disableNetwork { (error) in // Do offline things // ... }
Ziel c
[[FIRFirestore firestore] disableNetworkWithCompletion:^(NSError *_Nullable error) { // Do offline actions // ... }];
Kotlin+KTX
db.disableNetwork().addOnCompleteListener { // Do offline things // ... }
Java
db.disableNetwork() .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // Do offline things // ... } });
Dart
db.disableNetwork().then((_) { // Do offline things });
Verwenden Sie die folgende Methode, um den Netzwerkzugriff wieder zu aktivieren:
Web version 9
import { enableNetwork } from "firebase/firestore"; await enableNetwork(db); // Do online actions // ...
Web version 8
firebase.firestore().enableNetwork() .then(() => { // Do online actions // ... });
Schnell
Firestore.firestore().enableNetwork { (error) in // Do online things // ... }
Ziel c
[[FIRFirestore firestore] enableNetworkWithCompletion:^(NSError *_Nullable error) { // Do online actions // ... }];
Kotlin+KTX
db.enableNetwork().addOnCompleteListener { // Do online things // ... }
Java
db.enableNetwork() .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // Do online things // ... } });
Dart
db.enableNetwork().then((_) { // Back online });