Catch up on everthing we announced at this year's Firebase Summit. Learn more

Truy cập dữ liệu ngoại tuyến

Cloud Firestore hỗ trợ lưu trữ dữ liệu ngoại tuyến. Tính năng này lưu vào bộ nhớ cache một bản sao của dữ liệu Cloud Firestore mà ứng dụng của bạn đang sử dụng, vì vậy ứng dụng của bạn có thể truy cập dữ liệu khi thiết bị ngoại tuyến. Bạn có thể viết, đọc, nghe và truy vấn dữ liệu đã lưu trong bộ nhớ cache. Khi thiết bị trực tuyến trở lại, Cloud Firestore sẽ đồng bộ hóa mọi thay đổi cục bộ do ứng dụng của bạn thực hiện với phần phụ trợ Cloud Firestore.

Để sử dụng tính năng duy trì ngoại tuyến, bạn không cần thực hiện bất kỳ thay đổi nào đối với mã mà bạn sử dụng để truy cập dữ liệu Cloud Firestore. Với tính năng duy trì ngoại tuyến được bật, thư viện máy khách Cloud Firestore tự động quản lý truy cập dữ liệu trực tuyến và ngoại tuyến và đồng bộ hóa dữ liệu cục bộ khi thiết bị trực tuyến trở lại.

Định cấu hình tính duy trì ngoại tuyến

Khi khởi chạy Cloud Firestore, bạn có thể bật hoặc tắt tính năng duy trì ngoại tuyến:

  • Đối với các nền tảng Android và Apple, tính năng ổn định ngoại tuyến được bật theo mặc định. Để vô hiệu hóa bền bỉ, thiết lập PersistenceEnabled tùy chọn để false .
  • Đối với web, tính duy trì ngoại tuyến bị tắt theo mặc định. Để kích hoạt tính kiên trì, hãy gọi enablePersistence phương pháp. Bộ nhớ cache của Cloud Firestore không tự động bị xóa giữa các phiên. Do đó, nếu ứng dụng web của bạn xử lý thông tin nhạy cảm, hãy nhớ hỏi người dùng xem họ có đang sử dụng thiết bị đáng tin cậy hay không trước khi bật tính năng duy trì.

Phiên bản web 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

Phiên bản web 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
Nhanh
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
let settings = FirestoreSettings()
settings.isPersistenceEnabled = true

// Any additional options
// ...

// Enable offline data persistence
let db = Firestore.firestore()
db.settings = settings
Objective-C
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
FIRFirestoreSettings *settings = [[FIRFirestoreSettings alloc] init];
settings.persistenceEnabled = YES;

// Any additional options
// ...

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

Java

FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
        .setPersistenceEnabled(true)
        .build();
db.setFirestoreSettings(settings);

Kotlin + KTX

val settings = firestoreSettings {
    isPersistenceEnabled = true
}
db.firestoreSettings = settings

Định cấu hình kích thước bộ nhớ cache

Khi tính năng duy trì được bật, Cloud Firestore lưu trữ mọi tài liệu nhận được từ chương trình phụ trợ để truy cập ngoại tuyến. Cloud Firestore đặt ngưỡng mặc định cho kích thước bộ nhớ cache. Sau khi vượt quá mặc định, Cloud Firestore định kỳ cố gắng dọn dẹp các tài liệu cũ hơn, không sử dụng. Bạn có thể định cấu hình ngưỡng kích thước bộ nhớ cache khác hoặc tắt hoàn toàn quy trình dọn dẹp:

Phiên bản web 9

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

const firestoreDb = initializeFirestore(app, {
  cacheSizeBytes: CACHE_SIZE_UNLIMITED
});

Phiên bản web 8

firebase.firestore().settings({
    cacheSizeBytes: firebase.firestore.CACHE_SIZE_UNLIMITED
});
Nhanh
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
// 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
Objective-C
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
// 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;
  

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

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

Nghe dữ liệu ngoại tuyến

Trong khi thiết bị ngoại tuyến, nếu bạn đã bật tính năng duy trì ngoại tuyến, người nghe của bạn sẽ nhận được các sự kiện nghe khi dữ liệu được lưu trong bộ nhớ cache cục bộ thay đổi. Bạn có thể nghe tài liệu, bộ sưu tập và truy vấn.

Để kiểm tra xem bạn đang nhận dữ liệu từ máy chủ hoặc bộ nhớ cache, sử dụng fromCache tài sản trên SnapshotMetadata trong trường hợp ảnh chụp của bạn. Nếu fromCachetrue , các dữ liệu đến từ bộ nhớ cache và có thể là cũ hoặc không đầy đủ. Nếu fromCachefalse , dữ liệu đầy đủ và hiện tại với các bản cập nhật mới nhất trên máy chủ.

Theo mặc định, không có sự kiện được nâng lên nếu chỉ SnapshotMetadata thay đổi. Nếu bạn dựa trên fromCache giá trị, chỉ định includeMetadataChanges nghe tùy chọn khi bạn đính kèm xử lý lắng nghe bạn.

Phiên bản web 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);
    });
});

Phiên bản web 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);
      });
  });
Nhanh
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
// 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)")
}
Objective-C
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
// 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);
    }];

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

            }
        });

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

Nhận dữ liệu ngoại tuyến

Nếu bạn nhận được tài liệu trong khi thiết bị ngoại tuyến, Cloud Firestore sẽ trả lại dữ liệu từ bộ nhớ cache.

Khi truy vấn một bộ sưu tập, một kết quả trống được trả về nếu không có tài liệu được lưu trong bộ nhớ cache. Khi tìm nạp một tài liệu cụ thể, một lỗi sẽ được trả về thay thế.

Truy vấn dữ liệu ngoại tuyến

Truy vấn hoạt động với tính ổn định ngoại tuyến. Bạn có thể truy xuất kết quả của các truy vấn bằng cách lấy trực tiếp hoặc bằng cách lắng nghe, như được mô tả trong các phần trước. Bạn cũng có thể tạo truy vấn mới trên dữ liệu lưu trữ cục bộ trong khi thiết bị ngoại tuyến, nhưng ban đầu các truy vấn sẽ chỉ chạy trên các tài liệu được lưu trong bộ nhớ cache.

Tắt và bật quyền truy cập mạng

Bạn có thể sử dụng phương pháp bên dưới để vô hiệu hóa quyền truy cập mạng cho ứng dụng Cloud Firestore của mình. Trong khi quyền truy cập mạng bị vô hiệu hóa, tất cả các trình nghe ảnh chụp nhanh và các yêu cầu tài liệu sẽ truy xuất kết quả từ bộ đệm. Các thao tác ghi được xếp hàng đợi cho đến khi quyền truy cập mạng được kích hoạt lại.

Phiên bản web 9

import { disableNetwork } from "firebase/firestore"; 

await disableNetwork(db);
console.log("Network disabled!");
// Do offline actions
// ...

Phiên bản web 8

firebase.firestore().disableNetwork()
    .then(() => {
        // Do offline actions
        // ...
    });
Nhanh
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
Firestore.firestore().disableNetwork { (error) in
    // Do offline things
    // ...
}
Objective-C
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
[[FIRFirestore firestore] disableNetworkWithCompletion:^(NSError *_Nullable error) {
  // Do offline actions
  // ...
}];

Java

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

Sử dụng phương pháp sau để kích hoạt lại quyền truy cập mạng:

Phiên bản web 9

import { enableNetwork } from "firebase/firestore"; 

await enableNetwork(db);
// Do online actions
// ...

Phiên bản web 8

firebase.firestore().enableNetwork()
    .then(() => {
        // Do online actions
        // ...
    });
Nhanh
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
Firestore.firestore().enableNetwork { (error) in
    // Do online things
    // ...
}
Objective-C
Lưu ý: Sản phẩm này không có sẵn trên Clip tiêu watchos và App.
[[FIRFirestore firestore] enableNetworkWithCompletion:^(NSError *_Nullable error) {
  // Do online actions
  // ...
}];

Java

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