Cloud Firestore支持離線數據持久性。此功能緩存您的應用程序正在使用的Cloud Firestore數據的副本,因此您的應用程序可以在設備離線時訪問數據。您可以寫入,讀取,收聽和查詢緩存的數據。設備重新聯機後,Cloud Firestore會將您的應用所做的所有本地更改同步到Cloud Firestore後端。
要使用離線持久性,您無需對用於訪問Cloud Firestore數據的代碼進行任何更改。啟用離線持久性後,Cloud Firestore客戶端庫會自動管理在線和離線數據訪問,並在設備恢復在線狀態時同步本地數據。
配置離線持久性
初始化Cloud Firestore時,可以啟用或禁用離線持久性:
- 對於Android和iOS,默認情況下啟用離線持久性。要禁用持久性,請將
PersistenceEnabled
選項設置為false
。 - 對於Web,默認情況下禁用離線持久性。要啟用持久性,請調用
enablePersistence
方法。會話之間不會自動清除Cloud Firestore的緩存。因此,如果您的Web應用程序處理了敏感信息,請確保在啟用持久性之前先詢問用戶是否在受信任的設備上。
Web v8
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
Web v9
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
迅速
let settings = FirestoreSettings() settings.isPersistenceEnabled = true // Any additional options // ... // Enable offline data persistence let db = Firestore.firestore() db.settings = settings
物鏡
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init]; settings.persistenceEnabled = YES; // Any additional options // ... // Enable offline data persistence FIRFirestore *db = [FIRFirestore firestore]; db.settings = settings;
爪哇
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder() .setPersistenceEnabled(true) .build(); db.setFirestoreSettings(settings);
Kotlin + KTX
val settings = firestoreSettings { isPersistenceEnabled = true } db.firestoreSettings = settings
配置緩存大小
啟用持久性後,Cloud Firestore會緩存從後端收到的每個文檔,以供脫機訪問。 Cloud Firestore設置了緩存大小的默認閾值。超過默認值後,Cloud Firestore會定期嘗試清理較舊的未使用文檔。您可以配置其他緩存大小閾值或完全禁用清理過程:
Web v8
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
Web v9
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
網頁
// The default cache size threshold is 40 MB. Configure "cacheSizeBytes" // for a different threshold (minimum 1 MB) or set to "CACHE_SIZE_UNLIMITED" // to disable clean-up. firebase.firestore().settings({ cacheSizeBytes: firebase.firestore.CACHE_SIZE_UNLIMITED }); firebase.firestore().enablePersistence()
迅速
// 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
物鏡
第0692章爪哇
// 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);
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
收聽離線數據
設備處於脫機狀態時,如果啟用了脫機持久性,則本地緩存的數據更改時,偵聽器將接收偵聽事件。您可以收聽文檔,集合和查詢。
要檢查您是從服務器還是從緩存接收數據,請在快照事件中使用SnapshotMetadata
上的fromCache
屬性。如果fromCache
為true
,則數據來自緩存,並且可能是陳舊的或不完整的。如果fromCache
為false
,則數據是完整的並且是服務器上的最新更新的最新數據。
默認情況下,如果僅更改SnapshotMetadata
,則不會引發任何事件。如果您依賴fromCache
值,則在附加偵聽處理程序時,請指定includeMetadataChanges
偵聽選項。
Web v8
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); }); });
Web v9
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); }); });
迅速
// 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)") }
物鏡
// 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); }];
爪哇
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); } } });
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") } }
獲取離線數據
如果您在設備離線時獲取文檔,則Cloud Firestore會從緩存中返回數據。
查詢集合時,如果沒有緩存的文檔,則返回空結果。提取特定文檔時,將返回錯誤。
查詢離線數據
查詢具有離線持久性。您可以使用直接獲取或通過偵聽來檢索查詢的結果,如前幾節所述。您還可以在設備離線時對本地保留的數據創建新查詢,但是這些查詢最初只會針對緩存的文檔運行。
禁用和啟用網絡訪問
您可以使用以下方法為Cloud Firestore客戶端禁用網絡訪問。禁用網絡訪問後,所有快照偵聽器和文檔請求都將從緩存中檢索結果。將寫操作排隊,直到重新啟用網絡訪問。
Web v8
firebase.firestore().disableNetwork() .then(() => { // Do offline actions // ... });
Web v9
import { disableNetwork } from "firebase/firestore"; await disableNetwork(db); console.log("Network disabled!"); // Do offline actions // ...
迅速
第046章物鏡
[[FIRFirestore firestore] disableNetworkWithCompletion:^(NSError *_Nullable error) { // Do offline actions // ... }];
爪哇
db.disableNetwork() .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // Do offline things // ... } });
Kotlin + KTX
db.disableNetwork().addOnCompleteListener { // Do offline things // ... }
使用以下方法重新啟用網絡訪問:
Web v8
firebase.firestore().enableNetwork() .then(() => { // Do online actions // ... });
Web v9
import { enableNetwork } from "firebase/firestore"; await enableNetwork(db); // Do online actions // ...
迅速
Firestore.firestore().enableNetwork { (error) in // Do online things // ... }
物鏡
[[FIRFirestore firestore] enableNetworkWithCompletion:^(NSError *_Nullable error) { // Do online actions // ... }];
爪哇
db.enableNetwork() .addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { // Do online things // ... } });
Kotlin + KTX
db.enableNetwork().addOnCompleteListener { // Do online things // ... }