离线访问数据

离线访问数据

Cloud Firestore 支持离线数据持久化。这一功能会为您的应用正在使用的 Cloud Firestore 数据缓存一份副本,以便让您的应用可以在设备离线时访问数据。您可以写入、读取、监听和查询缓存的数据。当设备恢复在线状态时,Cloud Firestore 会将您的应用在本地所做的任何更改同步到 Cloud Firestore 后端。

注意:只有 Android、Apple 和 Web 应用才支持离线持久化。

您无需更改用于访问 Cloud Firestore 数据的代码,即可使用离线持久化功能。启用离线持久化后,Cloud Firestore 客户端库会自动管理在线和离线数据访问,并在设备恢复在线状态时同步本地数据。

配置离线持久化

在初始化 Cloud Firestore 时,您可以启用或停用离线持久化:

对于 Android 和 Apple 平台,离线持久化默认处于启用状态。如需停用持久化,请将 PersistenceEnabled 选项设置为 false。

对于 Web 应用,离线持久化默认处于停用状态。如需启用持久化,请调用 enablePersistence 方法。在不同会话之间切换时,系统不会自动清除 Cloud Firestore 的缓存。因此,如果您的 Web 应用涉及到敏感信息的处理,请务必在启用持久化之前询问用户其设备是否可信。

重要提示:对于 Web 应用,只有 Chrome、Safari 和 Firefox 网络浏览器支持离线持久化。

Web

详细了解可实现摇树优化的 Web v9 模块化 SDK,并从 v8 升级。

// Memory cache is the default if no config is specified.

initializeFirestore(app);

// This is the default behavior if no persistence is specified.

initializeFirestore(app, {localCache: memoryLocalCache()});

// Defaults to single-tab persistence if no tab manager is specified.

initializeFirestore(app, {localCache: persistentLocalCache(/*settings*/{})});

// Same as `initializeFirestore(app, {localCache: persistentLocalCache(/*settings*/{})})`,

// but more explicit about tab management.

initializeFirestore(app,

{localCache:

persistentLocalCache(/*settings*/{tabManager: persistentSingleTabManager()})

});

// Use multi-tab IndexedDb persistence.

initializeFirestore(app,

{localCache:

persistentLocalCache(/*settings*/{tabManager: persistentMultipleTabManager()})

});

Web

详细了解可实现摇树优化的 Web v9 模块化 SDK,并从 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 successfullytest.firestore.js

Swift

注意:此产品不适用于 watchOS 和 App Clip 目标。

let settings = FirestoreSettings()

// Use memory-only cache

settings.cacheSettings =

MemoryCacheSettings(garbageCollectorSettings: MemoryLRUGCSettings())

// Use persistent disk cache, with 100 MB cache size

settings.cacheSettings = PersistentCacheSettings(sizeBytes: 100 * 1024 * 1024 as NSNumber)

// Any additional options

// ...

// Enable offline data persistence

let db = Firestore.firestore()

db.settings = settingsViewController.swift

Objective-C

注意:此产品不适用于 watchOS 和 App Clip 目标。

FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init];

// Use memory-only cache

settings.cacheSettings = [[FIRMemoryCacheSettings alloc]

initWithGarbageCollectorSettings:[[FIRMemoryLRUGCSettings alloc] init]];

// Use persistent disk cache (default behavior)

// This example uses 100 MB.

settings.cacheSettings = [[FIRPersistentCacheSettings alloc]

initWithSizeBytes:@(100 * 1024 * 1024)];

// Any additional options

// ...

// Enable offline data persistence

FIRFirestore *db = [FIRFirestore firestore];

db.settings = settings;ViewController.m

Kotlin

val settings = firestoreSettings {

// Use memory cache

setLocalCacheSettings(memoryCacheSettings {})

// Use persistent disk cache (default)

setLocalCacheSettings(persistentCacheSettings {})

}

db.firestoreSettings = settingsDocSnippets.kt

Java

FirebaseFirestoreSettings settings =

new FirebaseFirestoreSettings.Builder(db.getFirestoreSettings())

// Use memory-only cache

.setLocalCacheSettings(MemoryCacheSettings.newBuilder().build())

// Use persistent disk cache (default)

.setLocalCacheSettings(PersistentCacheSettings.newBuilder()

.build())

.build();

db.setFirestoreSettings(settings);DocSnippets.java

Dart

// Apple and Android

db.settings = const Settings(persistenceEnabled: true);

// Web

await db

.enablePersistence(const PersistenceSettings(synchronizeTabs: true));firestore.dart

配置缓存大小

启用持久化后,Cloud Firestore 会缓存从后端接收的每个文档以便在离线状态下进行访问。Cloud Firestore 会为缓存大小设置默认阈值。超出默认值后,Cloud Firestore 会定期尝试清理较旧的未使用文档。您可以配置不同的缓存大小阈值,也可以完全停用清理功能:

Web

import { initializeFirestore, CACHE_SIZE_UNLIMITED } from "firebase/firestore";

const firestoreDb = initializeFirestore(app, {

cacheSizeBytes: CACHE_SIZE_UNLIMITED

});fs_setup_cache.js

Web

详细了解可实现摇树优化的模块化 Web API 及其相对于命名空间型 API 的优势。firebase.firestore().settings({

cacheSizeBytes: firebase.firestore.CACHE_SIZE_UNLIMITED

});test.firestore.js

Swift

注意:此产品不适用于 watchOS 和 App Clip 目标。

// 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

// Set cache size to 100 MB

settings.cacheSettings = PersistentCacheSettings(sizeBytes: 100 * 1024 * 1024 as NSNumber)

Firestore.firestore().settings = settingsViewController.swift

Objective-C

注意:此产品不适用于 watchOS 和 App Clip 目标。

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

// Set cache size to 100 MB

settings.cacheSettings =

[[FIRPersistentCacheSettings alloc] initWithSizeBytes:@(100 * 1024 * 1024)];

[FIRFirestore firestore].settings = settings;ViewController.m

Kotlin

// 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,

);firestore.dart

监听离线数据

当设备离线时,如果您已启用离线持久化,则当本地缓存的数据发生更改时,您的监听器将收到监听事件。您可以监听文档、集合和查询。

如需检查您收到的数据是来自服务器还是来自缓存,可使用快照事件的 SnapshotMetadata 中的 fromCache 属性。如果 fromCache 为 true,则说明数据来自缓存,可能是过时的或不完整的。如果 fromCache 为 false,则说明数据是完整的,并且与服务器上的最新更新保持一致。

默认情况下,如果只有 SnapshotMetadata 发生更改,则不会引发任何事件。如果您依赖于 fromCache 值,请在附加监听处理程序时指定 includeMetadataChanges 监听选项。

Web

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

});

});use_from_cache.js

Web

详细了解可实现摇树优化的模块化 Web API 及其相对于命名空间型 API 的优势。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);

});

});test.firestore.js

Swift

注意:此产品不适用于 watchOS 和 App Clip 目标。

// 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)")

}ViewController.swift

Objective-C

注意:此产品不适用于 watchOS 和 App Clip 目标。

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

}];ViewController.m

Kotlin

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

}

}DocSnippets.kt

Java

db.collection("cities").whereEqualTo("state", "CA")

.addSnapshotListener(MetadataChanges.INCLUDE, new EventListener() {

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

}

}

});DocSnippets.java

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

}

}

});firestore.dart

获取离线数据

如果您在设备离线时获取某个文档,Cloud Firestore 会从缓存中返回数据。

查询集合时,如果没有缓存的文档,系统会返回空结果。提取特定文档时,系统会返回错误。

查询离线数据

查询功能可与离线持久化功能结合使用。您可以直接使用 get 方法或通过监听(如前面的部分所述)来检索查询的结果。当设备离线时,您也可以针对已在本地永久保存的数据创建新的查询,但这些查询最开始只会针对缓存的文档运行。

配置离线查询索引

默认情况下,在执行离线查询时,Firestore SDK 会在其本地缓存中扫描集合内包含的所有文档。鉴于此默认行为,如果用户长时间处于离线状态,离线查询的性能可能会受到影响。

启用持久缓存后,您可以通过允许 SDK 自动创建本地查询索引来提高离线查询的性能。

默认情况下,自动编入索引功能处于停用状态。您的应用每次启动时都必须启用自动编入索引功能。按如下所示控制是否启用自动编入索引功能。

Swift

if let indexManager = Firestore.firestore().persistentCacheIndexManager {

// Indexing is disabled by default

indexManager.enableIndexAutoCreation()

} else {

print("indexManager is nil")

}

Objective-C

PersistentCacheIndexManager *indexManager = [FIRFirestore firestore].persistentCacheIndexManager;

if (indexManager) {

// Indexing is disabled by default

[indexManager enableIndexAutoCreation];

}

Kotlin

// return type: PersistentCacheManager?

Firebase.firestore.persistentCacheIndexManager?.apply {

// Indexing is disabled by default

enableIndexAutoCreation()

} ?: println("indexManager is null")

Java

// return type: @Nullable PersistentCacheIndexManager

PersistentCacheIndexManager indexManager = FirebaseFirestore.getInstance().getPersistentCacheIndexManager();

if (indexManager != null) {

// Indexing is disabled by default

indexManager.enableIndexAutoCreation();

}

// If not check indexManager != null, IDE shows warning: Method invocation 'enableIndexAutoCreation' may produce 'NullPointerException'

FirebaseFirestore.getInstance().getPersistentCacheIndexManager().enableIndexAutoCreation();

启用自动编入索引功能后,SDK 会评估哪些集合具有大量缓存的文档,并优化本地查询的性能。

SDK 提供了一种删除查询索引的方法。

停用和启用网络访问

您可以使用以下方法为您的 Cloud Firestore 客户端停用网络访问权限。网络访问权限停用后,所有快照监听器和文档请求都将从缓存中检索结果。写入操作会排入队列,直到网络访问权限重新启用。

Web

import { disableNetwork } from "firebase/firestore";

await disableNetwork(db);

console.log("Network disabled!");

// Do offline actions

// ...disable_network.js

Web

详细了解可实现摇树优化的模块化 Web API 及其相对于命名空间型 API 的优势。firebase.firestore().disableNetwork()

.then(() => {

// Do offline actions

// ...

});test.firestore.js

Swift

注意:此产品不适用于 watchOS 和 App Clip 目标。

Firestore.firestore().disableNetwork { (error) in

// Do offline things

// ...

}ViewController.swift

Objective-C

注意:此产品不适用于 watchOS 和 App Clip 目标。

[[FIRFirestore firestore] disableNetworkWithCompletion:^(NSError *_Nullable error) {

// Do offline actions

// ...

}];ViewController.m

Kotlin

db.disableNetwork().addOnCompleteListener {

// Do offline things

// ...

}DocSnippets.kt

Java

db.disableNetwork()

.addOnCompleteListener(new OnCompleteListener() {

@Override

public void onComplete(@NonNull Task task) {

// Do offline things

// ...

}

});DocSnippets.java

Dart

db.disableNetwork().then((_) {

// Do offline things

});firestore.dart

使用以下方法可重新启用网络访问权限:

Web

import { enableNetwork } from "firebase/firestore";

await enableNetwork(db);

// Do online actions

// ...enable_network.js

Web

详细了解可实现摇树优化的模块化 Web API 及其相对于命名空间型 API 的优势。firebase.firestore().enableNetwork()

.then(() => {

// Do online actions

// ...

});test.firestore.js

Swift

注意:此产品不适用于 watchOS 和 App Clip 目标。

Firestore.firestore().enableNetwork { (error) in

// Do online things

// ...

}ViewController.swift

Objective-C

注意:此产品不适用于 watchOS 和 App Clip 目标。

[[FIRFirestore firestore] enableNetworkWithCompletion:^(NSError *_Nullable error) {

// Do online actions

// ...

}];ViewController.m

Kotlin

db.enableNetwork().addOnCompleteListener {

// Do online things

// ...

}DocSnippets.kt

Java

db.enableNetwork()

.addOnCompleteListener(new OnCompleteListener() {

@Override

public void onComplete(@NonNull Task task) {

// Do online things

// ...

}

});DocSnippets.java

Dart

db.enableNetwork().then((_) {

// Back online

});firestore.dart

相关推荐

GAGAMAGA(色系军团) 365英国上市网正规吗

GAGAMAGA(色系军团)

08-02 👁️ 7640
Windows10 IIS Web服务器安装配置 365英国上市网正规吗
啥是ip受限(什么是ip受限制) 博大365