启用离线数据

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

您不必对访问 Cloud Firestore 数据时所用的代码进行任何更改,就可以使用离线持久化功能。启用离线持久化后,Cloud Firestore 客户端库会自动管理在线和离线数据访问,并在设备重新在线时同步本地数据。

配置离线持久化

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

  • 对于 Android 和 iOS 版应用,离线持久化默认为启用状态。要停用持久化,请将 PersistenceEnabled 选项设置为 false
  • 对于网页应用,离线持久化默认为停用状态。要启用持久化,可调用 enablePersistence 方法。在各个会话之间切换时,系统不会自动清除 Cloud Firestore 的缓存。因此,如果您的网页应用涉及到敏感信息的处理,请务必在启用持久化之前询问用户其设备是否可信。
网页
firebase.initializeApp({
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  projectId: '### CLOUD FIRESTORE PROJECT ID ###',
}
);

firebase.firestore().enablePersistence()
  .then(function() {
      // Initialize Cloud Firestore through firebase
      var db = firebase.firestore();
  })
  .catch(function(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
          // ...
      }
  });
  
Android
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
        .setPersistenceEnabled(true)
        .build();
db.setFirestoreSettings(settings);
  
Swift
let settings = FirestoreSettings()
settings.isPersistenceEnabled = true

// Any additional options
// ...

// Enable offline data persistence
let db = Firestore.firestore()
db.settings = settings
Objective-C
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init];
settings.persistenceEnabled = YES;

// Any additional options
// ...

// Enable offline data persistence
FIRFirestore *db = [FIRFirestore firestore];
db.settings = settings;
  

侦听离线数据

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

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

默认情况下,如果只有 SnapshotMetadata 发生更改,并不会引发任何事件。如果您需要侦听 fromCache 值的变化,请在附加侦听处理程序时指定 includeMetadataChanges 侦听选项。

网页
db.collection("cities").where("state", "==", "CA")
  .onSnapshot({ includeQueryMetadataChanges: true }, function(snapshot) {
      snapshot.docChanges.forEach(function(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);
      });
  });
 
Android
db.collection("cities").whereEqualTo("state", "CA")
        .addSnapshotListener(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);
                }

            }
        });
Swift
// Listen to metadata updates to receive a server snapshot even if
// the data is the same as the cached data.
let options = QueryListenOptions()
options.includeQueryMetadataChanges(true)

db.collection("cities").whereField("state", isEqualTo: "CA")
    .addSnapshotListener(options: options) { 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)")
}
Objective-C
// Listen to metadata updates to receive a server snapshot even if
// the data is the same as the cached data.
FIRQueryListenOptions *options = [FIRQueryListenOptions options];
[options includeQueryMetadataChanges:YES];
[[[db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"]
    addSnapshotListenerWithOptions:options
    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);
    }];
  

获取离线数据

如果您在设备离线时获取文档,Cloud Firestore 会从缓存中返回数据。如果缓存不包含该文档的数据,或该文档不存在,则 get 调用会返回一个错误。

查询离线数据

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

发送以下问题的反馈:

此网页
需要帮助?请访问我们的支持页面