Activer les données hors connexion

Cloud Firestore est compatible avec la persistance des données hors connexion. Cette fonctionnalité met en cache une copie des données Cloud Firestore utilisées activement par votre application, afin que votre application puisse accéder aux données lorsque l'appareil est hors connexion. Vous pouvez écrire, lire, écouter et interroger les données mises en cache. Lorsque l'appareil est de nouveau en ligne, Cloud Firestore synchronise toutes les modifications locales apportées par votre application au backend Cloud Firestore.

Pour utiliser la persistance hors connexion, vous n'avez pas besoin d'apporter de modifications au code que vous utilisez pour accéder aux données Cloud Firestore. Si la persistance hors connexion est activée, la bibliothèque cliente de Cloud Firestore gère automatiquement l'accès aux données en ligne et hors connexion, et synchronise les données locales lorsque l'appareil est de nouveau connecté.

Configurer la persistance hors connexion

Lorsque vous initialisez Cloud Firestore, vous pouvez activer ou désactiver la persistance hors connexion :

  • Pour Android et iOS, la persistance hors connexion est activée par défaut. Pour désactiver la persistance, définissez l'option PersistenceEnabled sur false.
  • Pour le Web, la persistance hors connexion est désactivée par défaut. Pour activer la persistance, appelez la méthode enablePersistence. Le cache de Cloud Firestore n'est pas automatiquement vidé entre les sessions. Par conséquent, si votre application Web traite des informations sensibles, demandez à l'utilisateur s'il utilise un appareil fiable avant d'activer la persistance
Web
firebase.firestore().enablePersistence()
  .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
          // ...
      }
  });
// Subsequent queries will use persistence, if it was enabled successfully
  
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;
  
Java
Android
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
        .setPersistenceEnabled(true)
        .build();
db.setFirestoreSettings(settings);
Kotlin
Android
val settings = FirebaseFirestoreSettings.Builder()
        .setPersistenceEnabled(true)
        .build()
db.firestoreSettings = settings

Configurer la taille du cache

Lorsque la persistance est activée, Cloud Firestore met en cache tous les documents reçus du backend pour un accès hors connexion. Cloud Firestore définit un seuil par défaut pour la taille du cache. Une fois la valeur par défaut dépassée, Cloud Firestore tente régulièrement de nettoyer les documents inutilisés. Vous pouvez configurer un autre seuil pour la taille du cache ou désactiver complètement le processus de nettoyage :

Web
// 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()
  
Swift
// 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
// 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
Android

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

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

Écouter des données hors connexion

Lorsque l'appareil est hors connexion, si vous avez activé la persistance hors connexion, vos écouteurs reçoivent des événements d'écoute lorsque les données mises en cache localement sont modifiées. Vous pouvez écouter des documents, des collections et des requêtes.

Pour vérifier si vous recevez des données du serveur ou du cache, utilisez la propriété fromCache du SnapshotMetadata de votre événement instantané. Si fromCache correspond à true, les données proviennent du cache et peuvent être obsolètes ou incomplètes. Si fromCache correspond à false, les données sont complètes et actualisées avec les dernières mises à jour sur le serveur.

Par défaut, aucun événement n'est déclenché si seulement le SnapshotMetadata a été modifié. Si vous utilisez les valeurs fromCache, spécifiez l'option d'écoute includeMetadataChanges lorsque vous associez votre gestionnaire d'écoute.

Web
db.collection("cities").where("state", "==", "CA")
  .onSnapshot({ includeMetadataChanges: 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);
      });
  });
 
Swift
// 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
// 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
Android
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
Android
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")
            }
        }

Obtenir des données hors connexion

Si vous recevez un document alors que l'appareil est hors connexion, Cloud Firestore renvoie les données du cache. Si le cache ne contient pas de données pour ce document ou si le document n'existe pas, l'appel get renvoie une erreur.

Interroger les données hors connexion

L'interrogation fonctionne avec la persistance hors connexion. Vous pouvez récupérer les résultats des requêtes à travers un accès direct ou en écoutant, comme décrit dans les sections précédentes. Vous pouvez également créer de nouvelles requêtes sur des données conservées localement lorsque l'appareil est hors connexion, mais les requêtes ne seront exécutées que sur les documents mis en cache.

Désactiver et activer l'accès au réseau

Vous pouvez utiliser la méthode ci-dessous pour désactiver l'accès au réseau pour votre client Cloud Firestore. Lorsque l'accès au réseau est désactivé, tous les écouteurs d'instantanés et les requêtes de documents récupèrent les résultats à partir du cache. Les opérations d'écriture sont mises en attente jusqu'à ce que l'accès au réseau soit réactivé..

Web
firebase.firestore().disableNetwork()
    .then(function() {
        // Do offline actions
        // ...
    });
  
Swift
Firestore.firestore().disableNetwork { (error) in
    // Do offline things
    // ...
}
Objective-C
[[FIRFirestore firestore] disableNetworkWithCompletion:^(NSError *_Nullable error) {
  // Do offline actions
  // ...
}];
  
Java
Android
db.disableNetwork()
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                // Do offline things
                // ...
            }
        });
Kotlin
Android
db.disableNetwork().addOnCompleteListener {
    // Do offline things
    // ...
}

Pour réactiver l'accès au réseau, procédez comme suit :

Web
firebase.firestore().enableNetwork()
    .then(function() {
        // Do online actions
        // ...
    });
  
Swift
Firestore.firestore().enableNetwork { (error) in
    // Do online things
    // ...
}
Objective-C
[[FIRFirestore firestore] enableNetworkWithCompletion:^(NSError *_Nullable error) {
  // Do online actions
  // ...
}];
  
Java
Android
db.enableNetwork()
        .addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                // Do online things
                // ...
            }
        });
Kotlin
Android
db.enableNetwork().addOnCompleteListener {
    // Do online things
    // ...
}