Ikuti semua informasi yang diumumkan di Firebase Summit, dan pelajari bagaimana Firebase dapat membantu Anda mempercepat pengembangan aplikasi dan menjalankan aplikasi dengan percaya diri. Pelajari Lebih Lanjut

Akses data offline

Tetap teratur dengan koleksi Simpan dan kategorikan konten berdasarkan preferensi Anda.

Cloud Firestore mendukung persistensi data offline. Fitur ini meng-cache salinan data Cloud Firestore yang aktif digunakan aplikasi Anda, sehingga aplikasi Anda dapat mengakses data saat perangkat offline. Anda dapat menulis, membaca, mendengarkan, dan menanyakan data yang di-cache. Saat perangkat kembali online, Cloud Firestore menyinkronkan setiap perubahan lokal yang dibuat oleh aplikasi Anda ke backend Cloud Firestore.

Untuk menggunakan persistensi offline, Anda tidak perlu melakukan perubahan apa pun pada kode yang Anda gunakan untuk mengakses data Cloud Firestore. Dengan persistensi offline diaktifkan, pustaka klien Cloud Firestore secara otomatis mengelola akses data online dan offline serta menyinkronkan data lokal saat perangkat kembali online.

Konfigurasikan persistensi offline

Saat melakukan inisialisasi Cloud Firestore, Anda dapat mengaktifkan atau menonaktifkan persistensi offline:

  • Untuk platform Android dan Apple, persistensi offline diaktifkan secara default. Untuk menonaktifkan persistensi, setel opsi PersistenceEnabled ke false .
  • Untuk web, persistensi offline dinonaktifkan secara default. Untuk mengaktifkan persistensi, panggil metode enablePersistence . Cache Cloud Firestore tidak dihapus secara otomatis di antara sesi. Akibatnya, jika aplikasi web Anda menangani informasi sensitif, pastikan untuk bertanya kepada pengguna apakah mereka menggunakan perangkat tepercaya sebelum mengaktifkan persistensi.

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
Cepat
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
let settings = FirestoreSettings()
settings.isPersistenceEnabled = true

// Any additional options
// ...

// Enable offline data persistence
let db = Firestore.firestore()
db.settings = settings
Objective-C
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
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));

Konfigurasikan ukuran cache

Saat persistensi diaktifkan, Cloud Firestore meng-cache setiap dokumen yang diterima dari backend untuk akses offline. Cloud Firestore menyetel ambang batas default untuk ukuran cache. Setelah melebihi nilai default, Cloud Firestore mencoba membersihkan dokumen lama yang tidak digunakan secara berkala. Anda dapat mengonfigurasi ambang batas ukuran cache yang berbeda atau menonaktifkan proses pembersihan sepenuhnya:

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
});
Cepat
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
// 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
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
// 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,
);

Dengarkan data luring

Saat perangkat offline, jika Anda telah mengaktifkan persistensi offline, pendengar Anda akan menerima peristiwa mendengarkan saat data yang di-cache secara lokal berubah. Anda dapat mendengarkan dokumen, koleksi, dan kueri.

Untuk memeriksa apakah Anda menerima data dari server atau cache, gunakan properti fromCache di SnapshotMetadata di kejadian snapshot Anda. Jika fromCache bernilai true , data berasal dari cache dan mungkin basi atau tidak lengkap. Jika fromCache false , data lengkap dan terkini dengan pembaruan terbaru di server.

Secara default, tidak ada acara yang dimunculkan jika hanya SnapshotMetadata yang diubah. Jika Anda mengandalkan nilai fromCache , tentukan opsi mendengarkan includeMetadataChanges saat Anda memasang penangan mendengarkan.

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);
      });
  });
Cepat
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
// 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
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
// 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}");
    }
  }
});

Dapatkan data luring

Jika Anda mendapatkan dokumen saat perangkat offline, Cloud Firestore mengembalikan data dari cache.

Saat menanyakan koleksi, hasil kosong dikembalikan jika tidak ada dokumen yang di-cache. Saat mengambil dokumen tertentu, kesalahan malah dikembalikan.

Kueri data luring

Permintaan berfungsi dengan persistensi offline. Anda dapat mengambil hasil kueri dengan pengambilan langsung atau dengan mendengarkan, seperti yang dijelaskan di bagian sebelumnya. Anda juga dapat membuat kueri baru pada data yang disimpan secara lokal saat perangkat offline, tetapi kueri awalnya hanya akan berjalan pada dokumen yang di-cache.

Konfigurasikan indeks kueri luring

Secara default, Firestore SDK memindai semua dokumen dalam kumpulan di cache lokalnya saat menjalankan kueri offline. Dengan perilaku default ini, kinerja kueri luring dapat menurun saat pengguna luring untuk jangka waktu yang lama.

Anda dapat meningkatkan performa kueri offline dengan mengonfigurasi indeks kueri lokal:

Cepat

SDK platform Apple menyediakan metode setIndexConfiguration yang membaca konfigurasi berstruktur JSON yang sama yang digunakan untuk mengonfigurasi indeks di server, mengikuti format definisi indeks yang sama .

// You will normally read this from a file asset or cloud storage.
let indexConfigJson = """
  {
    indexes: [
        ...
    ],
    fieldOverrides: [
        ...
    ]
  }
"""

// Apply the configuration.
Firestore.firestore().setIndexConfiguration(indexConfigJson)
Objective-C

SDK platform Apple menyediakan setIndexConfiguration - metode yang membaca konfigurasi berstruktur JSON yang sama yang digunakan untuk mengonfigurasi indeks di server, mengikuti format definisi indeks yang sama .

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

Android SDK menyediakan metode setIndexConfiguration yang membaca konfigurasi berstruktur JSON yang sama yang digunakan untuk mengonfigurasi indeks di server, mengikuti format definisi indeks yang sama.

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

Android SDK menyediakan metode setIndexConfiguration yang membaca konfigurasi berstruktur JSON yang sama yang digunakan untuk mengonfigurasi indeks di server, mengikuti format definisi indeks yang sama.

// You will normally read this from a file asset or cloud storage.
val indexConfigJson = """
{
  indexes: [
      ...
  ],
  fieldOverrides: [
      ...
  ]
}
"""

// Apply the configuration.
FirebaseFirestore.getInstance().setIndexConfiguration(indexConfigJson)

Dart

Flutter SDK menyediakan metode setIndexConfigurationFromJSON yang membaca konfigurasi berstruktur JSON yang sama yang digunakan untuk mengonfigurasi indeks di server, mengikuti format definisi indeks yang sama.

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

Sebagai alternatif, Anda dapat menggunakan metode setIndexConfiguration untuk mengonfigurasi indeks dengan API berbasis kelas.

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

Konfigurasi indeks offline yang akan digunakan bergantung pada koleksi dan dokumen mana yang sering diakses aplikasi Anda saat offline dan performa offline yang Anda inginkan. Meskipun Anda dapat mengekspor konfigurasi indeks backend untuk digunakan pada klien, pola akses offline aplikasi Anda mungkin berbeda secara signifikan dari pola akses online, sehingga konfigurasi indeks online Anda mungkin tidak sesuai untuk digunakan secara offline. Koleksi dan dokumen mana yang Anda ingin aplikasi Anda akses secara offline dengan kinerja tinggi? Setelah menganalisis perilaku aplikasi, ikuti prinsip definisi indeks dari panduan pengindeksan .

Agar konfigurasi indeks offline tersedia untuk dimuat di aplikasi klien Anda:

  • kompilasi dan distribusikan dengan aplikasi Anda
  • unduh dari CDN
  • mengambilnya dari sistem penyimpanan seperti Cloud Storage for Firebase .

Nonaktifkan dan aktifkan akses jaringan

Anda dapat menggunakan metode di bawah ini untuk menonaktifkan akses jaringan untuk klien Cloud Firestore Anda. Saat akses jaringan dinonaktifkan, semua pendengar snapshot dan permintaan dokumen mengambil hasil dari cache. Operasi tulis diantrekan hingga akses jaringan diaktifkan kembali.

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
        // ...
    });
Cepat
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
Firestore.firestore().disableNetwork { (error) in
    // Do offline things
    // ...
}
Objective-C
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
[[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
});

Gunakan metode berikut untuk mengaktifkan kembali akses jaringan:

Web version 9

import { enableNetwork } from "firebase/firestore"; 

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

Web version 8

firebase.firestore().enableNetwork()
    .then(() => {
        // Do online actions
        // ...
    });
Cepat
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
Firestore.firestore().enableNetwork { (error) in
    // Do online things
    // ...
}
Objective-C
Catatan: Produk ini tidak tersedia di watchOS dan target Cuplikan Aplikasi.
[[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
});