Mit der Methode onSnapshot()
können Sie ein Dokument durch Listener überwachen lassen. Bei einem ersten Aufruf mit dem von Ihnen angegebenen Callback wird sofort ein Dokument-Snapshot mit dem aktuellen Inhalt des einzelnen Dokuments erstellt. Jedes Mal, wenn sich der Inhalt danach ändert, aktualisiert ein weiterer Aufruf den Dokument-Snapshot.
import { doc, onSnapshot } from "firebase/firestore"; const unsub = onSnapshot(doc(db, "cities", "SF"), (doc) => { console.log("Current data: ", doc.data()); });
db.collection("cities").doc("SF") .onSnapshot((doc) => { console.log("Current data: ", doc.data()); });
db.collection("cities").document("SF") .addSnapshotListener { documentSnapshot, error in guard let document = documentSnapshot else { print("Error fetching document: \(error!)") return } guard let data = document.data() else { print("Document data was empty.") return } print("Current data: \(data)") }
[[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"] addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching document: %@", error); return; } NSLog(@"Current data: %@", snapshot.data); }];
val docRef = db.collection("cities").document("SF") docRef.addSnapshotListener { snapshot, e -> if (e != null) { Log.w(TAG, "Listen failed.", e) return@addSnapshotListener } if (snapshot != null && snapshot.exists()) { Log.d(TAG, "Current data: ${snapshot.data}") } else { Log.d(TAG, "Current data: null") } }
final DocumentReference docRef = db.collection("cities").document("SF"); docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() { @Override public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen failed.", e); return; } if (snapshot != null && snapshot.exists()) { Log.d(TAG, "Current data: " + snapshot.getData()); } else { Log.d(TAG, "Current data: null"); } } });
final docRef = db.collection("cities").doc("SF"); docRef.snapshots().listen( (event) => print("current data: ${event.data()}"), onError: (error) => print("Listen failed: $error"), );
Oft möchten Sie, dass Ihre Benutzeroberfläche auf Änderungen am Inhalt eines Firestore-Dokuments oder einer Firestore-Sammlung reagiert. Dazu können Sie ein StreamBuilder
-Widget verwenden, das den Firestore-Snapshot-Stream nutzt:
class UserInformation extends StatefulWidget { @override _UserInformationState createState() => _UserInformationState(); } class _UserInformationState extends State<UserInformation> { final Stream<QuerySnapshot> _usersStream = FirebaseFirestore.instance.collection('users').snapshots(); @override Widget build(BuildContext context) { return StreamBuilder<QuerySnapshot>( stream: _usersStream, builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) { if (snapshot.hasError) { return const Text('Something went wrong'); } if (snapshot.connectionState == ConnectionState.waiting) { return const Text("Loading"); } return ListView( children: snapshot.data!.docs .map((DocumentSnapshot document) { Map<String, dynamic> data = document.data()! as Map<String, dynamic>; return ListTile( title: Text(data['full_name']), subtitle: Text(data['company']), ); }) .toList() .cast(), ); }, ); } }
DocumentReference doc_ref = db->Collection("cities").Document("SF"); doc_ref.AddSnapshotListener( [](const DocumentSnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { if (snapshot.exists()) { std::cout << "Current data: " << snapshot << std::endl; } else { std::cout << "Current data: null" << std::endl; } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not supported in the PHP client library
DocumentReference docRef = db.Collection("cities").Document("SF"); docRef.Listen(snapshot => { Debug.Log("Callback received document snapshot."); Debug.Log(String.Format("Document data for {0} document:", snapshot.Id)); Dictionary<string, object> city = snapshot.ToDictionary(); foreach (KeyValuePair<string, object> pair in city) { Debug.Log(String.Format("{0}: {1}", pair.Key, pair.Value)); } });
Ereignisse für lokale Änderungen
Durch lokale Schreibvorgänge in Ihrer Anwendung werden Snapshot-Listener unverzüglich aufgerufen. Dies liegt an einem wichtigen Feature namens "Latenzkompensation". Wenn Sie einen Schreibvorgang durchführen, werden die Listener über die neuen Daten benachrichtigt, bevor die Daten an das Back-End gesendet werden.
Abgerufene Dokumente haben das Attribut metadata.hasPendingWrites
, das angibt, ob das Dokument lokale Änderungen aufweist, die noch nicht in das Back-End geschrieben wurden. Sie können dieses Attribut verwenden, um die Quelle der von Ihrem Snapshot-Listener empfangenen Ereignisse zu ermitteln:
import { doc, onSnapshot } from "firebase/firestore"; const unsub = onSnapshot(doc(db, "cities", "SF"), (doc) => { const source = doc.metadata.hasPendingWrites ? "Local" : "Server"; console.log(source, " data: ", doc.data()); });
db.collection("cities").doc("SF") .onSnapshot((doc) => { var source = doc.metadata.hasPendingWrites ? "Local" : "Server"; console.log(source, " data: ", doc.data()); });
db.collection("cities").document("SF") .addSnapshotListener { documentSnapshot, error in guard let document = documentSnapshot else { print("Error fetching document: \(error!)") return } let source = document.metadata.hasPendingWrites ? "Local" : "Server" print("\(source) data: \(document.data() ?? [:])") }
[[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"] addSnapshotListener:^(FIRDocumentSnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching document: %@", error); return; } NSString *source = snapshot.metadata.hasPendingWrites ? @"Local" : @"Server"; NSLog(@"%@ data: %@", source, snapshot.data); }];
val docRef = db.collection("cities").document("SF") docRef.addSnapshotListener { snapshot, e -> if (e != null) { Log.w(TAG, "Listen failed.", e) return@addSnapshotListener } val source = if (snapshot != null && snapshot.metadata.hasPendingWrites()) { "Local" } else { "Server" } if (snapshot != null && snapshot.exists()) { Log.d(TAG, "$source data: ${snapshot.data}") } else { Log.d(TAG, "$source data: null") } }
final DocumentReference docRef = db.collection("cities").document("SF"); docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() { @Override public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen failed.", e); return; } String source = snapshot != null && snapshot.getMetadata().hasPendingWrites() ? "Local" : "Server"; if (snapshot != null && snapshot.exists()) { Log.d(TAG, source + " data: " + snapshot.getData()); } else { Log.d(TAG, source + " data: null"); } } });
final docRef = db.collection("cities").doc("SF"); docRef.snapshots().listen( (event) { final source = (event.metadata.hasPendingWrites) ? "Local" : "Server"; print("$source data: ${event.data()}"); }, onError: (error) => print("Listen failed: $error"), );
# Not yet supported in the Java client library
// Not yet supported in Python client library
DocumentReference doc_ref = db->Collection("cities").Document("SF"); doc_ref.AddSnapshotListener([](const DocumentSnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { const char* source = snapshot.metadata().has_pending_writes() ? "Local" : "Server"; if (snapshot.exists()) { std::cout << source << " data: " << snapshot.Get("name").string_value() << std::endl; } else { std::cout << source << " data: null" << std::endl; } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not yet supported in the Node.js client library
// Not yet supported in the Go client library
// Not supported in the PHP client library
DocumentReference docRef = db.Collection("cities").Document("SF"); docRef.Listen( snapshot => { string source = (snapshot != null && snapshot.Metadata.HasPendingWrites) ? "Local" : "Server"; string snapshotData = "null"; if (snapshot != null && snapshot.Exists) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); IDictionary<string, object> dict = snapshot.ToDictionary(); foreach (var KVPair in dict) { builder.Append($"{KVPair.Key}: {KVPair.Value}\n"); } snapshotData = builder.ToString(); } Debug.Log($"{source} data: ${snapshotData}"); });
// Not yet supported in the C# client library
// Not yet supported in the Ruby client library
Ereignisse für Metadatenänderungen
Wenn Sie ein Dokument, eine Sammlung oder eine Abfrage auf Änderungen überwachen lassen, können Sie Optionen übergeben, um den Detaillierungsgrad der Ereignisse zu steuern, die Ihr Listener erhalten soll.
Standardmäßig werden Listener nicht über Änderungen benachrichtigt, die sich nur auf Metadaten auswirken. Überlegen Sie, was geschieht, wenn Ihre Anwendung ein neues Dokument schreibt:
- Mit den neuen Daten wird unverzüglich ein Änderungsereignis ausgelöst. Das Dokument wurde noch nicht in das Back-End geschrieben. Das Flag für ausstehende Schreibvorgänge ist also
true
. - Das Dokument wird in das Back-End geschrieben.
- Das Back-End benachrichtigt den Client über den erfolgreichen Schreibvorgang. Es gibt keine Änderung an den Dokumentdaten, aber es gibt eine Änderung der Metadaten, da das Flag für ausstehende Schreibvorgänge jetzt
false
ist.
Wenn Sie Snapshot-Ereignisse erhalten möchten, sobald sich die Metadaten des Dokuments oder der Abfrage ändern, übergeben Sie beim Anhängen Ihres Listeners ein Optionsobjekt für die Überwachung.
import { doc, onSnapshot } from "firebase/firestore"; const unsub = onSnapshot( doc(db, "cities", "SF"), { includeMetadataChanges: true }, (doc) => { // ... });
db.collection("cities").doc("SF") .onSnapshot({ // Listen for document metadata changes includeMetadataChanges: true }, (doc) => { // ... });
// Listen to document metadata. db.collection("cities").document("SF") .addSnapshotListener(includeMetadataChanges: true) { documentSnapshot, error in // ... }
// Listen for metadata changes. [[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"] addSnapshotListenerWithIncludeMetadataChanges:YES listener:^(FIRDocumentSnapshot *snapshot, NSError *error) { // ... }];
// Listen for metadata changes to the document. val docRef = db.collection("cities").document("SF") docRef.addSnapshotListener(MetadataChanges.INCLUDE) { snapshot, e -> // ... }
// Listen for metadata changes to the document. DocumentReference docRef = db.collection("cities").document("SF"); docRef.addSnapshotListener(MetadataChanges.INCLUDE, new EventListener<DocumentSnapshot>() { @Override public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirebaseFirestoreException e) { // ... } });
final docRef = db.collection("cities").doc("SF"); docRef.snapshots(includeMetadataChanges: true).listen((event) { // ... });
// Not yet supported in the Java client library
// Not yet supported in Python client library
DocumentReference doc_ref = db->Collection("cities").Document("SF"); doc_ref.AddSnapshotListener( MetadataChanges::kInclude, [](const DocumentSnapshot& snapshot, Error error, const std::string& errorMsg) { /* ... */ });
// Not yet supported the Node.js client library
// Not yet supported in the Go client library
// Not supported in the PHP client library
DocumentReference docRef = db.Collection("cities").Document("SF"); docRef.Listen(MetadataChanges.Include, snapshot => { // ... });
// Not yet supported in the C# client library
// Not yet supported in the Ruby client library
Listener nur für lokale Änderungen konfigurieren
Cloud Firestore Snapshot-Listener erstellen einen ersten Snapshot aus dem lokalen Cache und rufen gleichzeitig entsprechende Daten vom Server ab.
In einigen Fällen möchten Sie möglicherweise keine weiteren Abrufe vom Server. Mit Client-SDKs können Sie Listener so konfigurieren, dass sie nur für Daten im lokalen Cache ausgelöst werden. So lassen sich unnötige Serveraufrufe und die damit verbundenen Kosten vermeiden und der clientseitige Cache wird genutzt, der lokale Daten und Mutationen widerspiegelt.
Hier werden Snapshot-Optionen im Clientcode festgelegt, um nur auf lokale Änderungen zu hören.
const unsubscribe = onSnapshot( doc(db, "cities", "SF"), { includeMetadataChanges: true, source:'cache' }, (documentSnapshot) => {//…} );
// Not yet supported in the Web namespaced API
// Set up listener options let options = SnapshotListenOptions() .withSource(ListenSource.cache) .withIncludeMetadataChanges(true) db.collection("cities").document("SF") .addSnapshotListener(options: options) { documentSnapshot, error in // ... }
// Set up listener options FIRSnapshotListenOptions *options = [[FIRSnapshotListenOptions alloc] init]; FIRSnapshotListenOptions *optionsWithSourceAndMetadata = [[options optionsWithIncludeMetadataChanges:YES] optionsWithSource:FIRListenSourceCache]; [[[self.db collectionWithPath:@"cities"] documentWithPath:@"SF"] addSnapshotListenerWithOptions:optionsWithSourceAndMetadata listener: ^ (FIRDocumentSnapshot * snapshot, NSError * error) { //… } ];
// Set up listener options val options = SnapshotListenOptions.Builder() .setMetadataChanges(MetadataChanges.INCLUDE) .setSource(ListenSource.CACHE) .build(); db.collection("cities").document("SF") .addSnapshotListener(options) { snapshot, error -> //… }
// Set up listener options SnapshotListenOptions options = new SnapshotListenOptions.Builder() .setMetadataChanges(MetadataChanges.INCLUDE) .setSource(ListenSource.CACHE) .build(); db.collection("cities").document("SF").addSnapshotListener(options, new EventListener<DocumentSnapshot>() { //… });
// Not yet supported in this client library
# Not yet supported in the Java client library
// Not yet supported in Python client library
// Not yet supported in the C++ client library
// Not yet supported in the Node.js client library
// Not yet supported in the Go client library
// Not yet supported in the PHP client library
// Not yet supported in the Unity client library
// Not yet supported in the C# client library
// Not yet supported in the Ruby client library
Mehrere Dokumente in einer Sammlung überwachen
Wie bei Dokumenten können Sie auch die Ergebnisse einer Abfrage mithilfe von onSnapshot()
anstelle von get()
überwachen. Dadurch wird ein Abfrage-Snapshot erstellt. So können Sie beispielsweise die Dokumente mit dem Status CA
überwachen:
import { collection, query, where, onSnapshot } from "firebase/firestore"; const q = query(collection(db, "cities"), where("state", "==", "CA")); const unsubscribe = onSnapshot(q, (querySnapshot) => { const cities = []; querySnapshot.forEach((doc) => { cities.push(doc.data().name); }); console.log("Current cities in CA: ", cities.join(", ")); });
db.collection("cities").where("state", "==", "CA") .onSnapshot((querySnapshot) => { var cities = []; querySnapshot.forEach((doc) => { cities.push(doc.data().name); }); console.log("Current cities in CA: ", cities.join(", ")); });
db.collection("cities").whereField("state", isEqualTo: "CA") .addSnapshotListener { querySnapshot, error in guard let documents = querySnapshot?.documents else { print("Error fetching documents: \(error!)") return } let cities = documents.compactMap { $0["name"] } print("Current cities in CA: \(cities)") }
[[[self.db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching documents: %@", error); return; } NSMutableArray *cities = [NSMutableArray array]; for (FIRDocumentSnapshot *document in snapshot.documents) { [cities addObject:document.data[@"name"]]; } NSLog(@"Current cities in CA: %@", cities); }];
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener { value, e -> if (e != null) { Log.w(TAG, "Listen failed.", e) return@addSnapshotListener } val cities = ArrayList<String>() for (doc in value!!) { doc.getString("name")?.let { cities.add(it) } } Log.d(TAG, "Current cites in CA: $cities") }
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot value, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "Listen failed.", e); return; } List<String> cities = new ArrayList<>(); for (QueryDocumentSnapshot doc : value) { if (doc.get("name") != null) { cities.add(doc.getString("name")); } } Log.d(TAG, "Current cites in CA: " + cities); } });
db .collection("cities") .where("state", isEqualTo: "CA") .snapshots() .listen((event) { final cities = []; for (var doc in event.docs) { cities.add(doc.data()["name"]); } print("cities in CA: ${cities.join(", ")}"); });
db->Collection("cities") .WhereEqualTo("state", FieldValue::String("CA")) .AddSnapshotListener([](const QuerySnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { std::vector<std::string> cities; std::cout << "Current cities in CA: " << error << std::endl; for (const DocumentSnapshot& doc : snapshot.documents()) { cities.push_back(doc.Get("name").string_value()); std::cout << "" << cities.back() << std::endl; } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not supported in the PHP client library
Query query = db.Collection("cities").WhereEqualTo("State", "CA"); ListenerRegistration listener = query.Listen(snapshot => { Debug.Log("Callback received query snapshot."); Debug.Log("Current cities in California:"); foreach (DocumentSnapshot documentSnapshot in snapshot.Documents) { Debug.Log(documentSnapshot.Id); } });
Der Snapshot-Handler erhält jedes Mal einen neuen Abfrage-Snapshot, wenn sich die Abfrageergebnisse ändern (d. h., wenn ein Dokument hinzugefügt, entfernt oder geändert wird).
Änderungen zwischen Snapshots ansehen
Oft ist es sinnvoll, sich die tatsächlichen Änderungen an Abfrageergebnissen zwischen Abfrage-Snapshots anzusehen, statt einfach den gesamten Abfrage-Snapshot zu verwenden. Zum Beispiel möchten Sie vielleicht einen Cache beibehalten, wenn einzelne Dokumente hinzugefügt, entfernt und geändert werden.
import { collection, query, where, onSnapshot } from "firebase/firestore"; const q = query(collection(db, "cities"), where("state", "==", "CA")); const unsubscribe = onSnapshot(q, (snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } if (change.type === "modified") { console.log("Modified city: ", change.doc.data()); } if (change.type === "removed") { console.log("Removed city: ", change.doc.data()); } }); });
db.collection("cities").where("state", "==", "CA") .onSnapshot((snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === "added") { console.log("New city: ", change.doc.data()); } if (change.type === "modified") { console.log("Modified city: ", change.doc.data()); } if (change.type === "removed") { console.log("Removed city: ", change.doc.data()); } }); });
db.collection("cities").whereField("state", isEqualTo: "CA") .addSnapshotListener { querySnapshot, error in guard let snapshot = querySnapshot else { print("Error fetching snapshots: \(error!)") return } snapshot.documentChanges.forEach { diff in if (diff.type == .added) { print("New city: \(diff.document.data())") } if (diff.type == .modified) { print("Modified city: \(diff.document.data())") } if (diff.type == .removed) { print("Removed city: \(diff.document.data())") } } }
[[[self.db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (snapshot == nil) { NSLog(@"Error fetching documents: %@", error); return; } for (FIRDocumentChange *diff in snapshot.documentChanges) { if (diff.type == FIRDocumentChangeTypeAdded) { NSLog(@"New city: %@", diff.document.data); } if (diff.type == FIRDocumentChangeTypeModified) { NSLog(@"Modified city: %@", diff.document.data); } if (diff.type == FIRDocumentChangeTypeRemoved) { NSLog(@"Removed city: %@", diff.document.data); } } }];
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener { snapshots, e -> if (e != null) { Log.w(TAG, "listen:error", e) return@addSnapshotListener } for (dc in snapshots!!.documentChanges) { when (dc.type) { DocumentChange.Type.ADDED -> Log.d(TAG, "New city: ${dc.document.data}") DocumentChange.Type.MODIFIED -> Log.d(TAG, "Modified city: ${dc.document.data}") DocumentChange.Type.REMOVED -> Log.d(TAG, "Removed city: ${dc.document.data}") } } }
db.collection("cities") .whereEqualTo("state", "CA") .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot snapshots, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "listen:error", e); return; } for (DocumentChange dc : snapshots.getDocumentChanges()) { switch (dc.getType()) { case ADDED: Log.d(TAG, "New city: " + dc.getDocument().getData()); break; case MODIFIED: Log.d(TAG, "Modified city: " + dc.getDocument().getData()); break; case REMOVED: Log.d(TAG, "Removed city: " + dc.getDocument().getData()); break; } } } });
db .collection("cities") .where("state", isEqualTo: "CA") .snapshots() .listen((event) { for (var change in event.docChanges) { switch (change.type) { case DocumentChangeType.added: print("New City: ${change.doc.data()}"); break; case DocumentChangeType.modified: print("Modified City: ${change.doc.data()}"); break; case DocumentChangeType.removed: print("Removed City: ${change.doc.data()}"); break; } } });
db->Collection("cities") .WhereEqualTo("state", FieldValue::String("CA")) .AddSnapshotListener([](const QuerySnapshot& snapshot, Error error, const std::string& errorMsg) { if (error == Error::kErrorOk) { for (const DocumentChange& dc : snapshot.DocumentChanges()) { switch (dc.type()) { case DocumentChange::Type::kAdded: std::cout << "New city: " << dc.document().Get("name").string_value() << std::endl; break; case DocumentChange::Type::kModified: std::cout << "Modified city: " << dc.document().Get("name").string_value() << std::endl; break; case DocumentChange::Type::kRemoved: std::cout << "Removed city: " << dc.document().Get("name").string_value() << std::endl; break; } } } else { std::cout << "Listen failed: " << error << std::endl; } });
// Not supported in the PHP client library
Query query = db.Collection("cities").WhereEqualTo("State", "CA"); ListenerRegistration listener = query.Listen(snapshot => { foreach (DocumentChange change in snapshot.GetChanges()) { if (change.ChangeType == DocumentChange.Type.Added) { Debug.Log(String.Format("New city: {0}", change.Document.Id)); } else if (change.ChangeType == DocumentChange.Type.Modified) { Debug.Log(String.Format("Modified city: {0}", change.Document.Id)); } else if (change.ChangeType == DocumentChange.Type.Removed) { Debug.Log(String.Format("Removed city: {0}", change.Document.Id)); } } });
Der Ausgangszustand kann direkt vom Server oder von einem lokalen Cache stammen. Wenn ein Zustand in einem lokalen Cache verfügbar ist, wird der Anfrage-Snapshot zuerst mit den Daten im Cache gefüllt und dann mit den Serverdaten aktualisiert, wenn der Client zum Serverzustand aufgeschlossen hat.
Listener trennen
Wenn Sie nicht mehr an der Überwachung der Daten interessiert sind, müssen Sie den Listener trennen, damit die Ereignis-Callbacks nicht mehr aufgerufen werden. Dadurch kann der Client aufhören, Bandbreite für den Empfang von Aktualisierungen zu verwenden. Beispiel:
import { collection, onSnapshot } from "firebase/firestore"; const unsubscribe = onSnapshot(collection(db, "cities"), () => { // Respond to data // ... }); // Later ... // Stop listening to changes unsubscribe();
var unsubscribe = db.collection("cities") .onSnapshot(() => { // Respond to data // ... }); // Later ... // Stop listening to changes unsubscribe();
let listener = db.collection("cities").addSnapshotListener { querySnapshot, error in // ... } // ... // Stop listening to changes listener.remove()
id<FIRListenerRegistration> listener = [[self.db collectionWithPath:@"cities"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { // ... }]; // ... // Stop listening to changes [listener remove];
val query = db.collection("cities") val registration = query.addSnapshotListener { snapshots, e -> // ... } // ... // Stop listening to changes registration.remove()
Query query = db.collection("cities"); ListenerRegistration registration = query.addSnapshotListener( new EventListener<QuerySnapshot>() { // ... }); // ... // Stop listening to changes registration.remove();
final collection = db.collection("cities"); final listener = collection.snapshots().listen((event) { // ... }); listener.cancel();
// Add a listener Query query = db->Collection("cities"); ListenerRegistration registration = query.AddSnapshotListener( [](const QuerySnapshot& snapshot, Error error, const std::string& errorMsg) { /* ... */ }); // Stop listening to changes registration.Remove();
// Not supported in the PHP client library
listener.Stop();
Fehler beim Überwachen behandeln
Eine Überwachung kann gelegentlich fehlschlagen, z. B. aufgrund von Sicherheitsberechtigungen oder bei dem Versuch, eine ungültige Abfrage zu überwachen. (Hier finden Sie weitere Informationen zu gültigen und ungültigen Abfragen.) Um diese Fehler zu behandeln, können Sie beim Anhängen des Snapshot-Listeners einen Fehler-Callback angeben. Nach einem Fehler empfängt der Listener keine weiteren Ereignisse mehr und muss daher nicht getrennt werden.
import { collection, onSnapshot } from "firebase/firestore"; const unsubscribe = onSnapshot( collection(db, "cities"), (snapshot) => { // ... }, (error) => { // ... });
db.collection("cities") .onSnapshot((snapshot) => { // ... }, (error) => { // ... });
db.collection("cities") .addSnapshotListener { querySnapshot, error in if let error = error { print("Error retreiving collection: \(error)") } }
[[self.db collectionWithPath:@"cities"] addSnapshotListener:^(FIRQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error retreving collection: %@", error); } }];
db.collection("cities") .addSnapshotListener { snapshots, e -> if (e != null) { Log.w(TAG, "listen:error", e) return@addSnapshotListener } for (dc in snapshots!!.documentChanges) { if (dc.type == DocumentChange.Type.ADDED) { Log.d(TAG, "New city: ${dc.document.data}") } } }
db.collection("cities") .addSnapshotListener(new EventListener<QuerySnapshot>() { @Override public void onEvent(@Nullable QuerySnapshot snapshots, @Nullable FirebaseFirestoreException e) { if (e != null) { Log.w(TAG, "listen:error", e); return; } for (DocumentChange dc : snapshots.getDocumentChanges()) { if (dc.getType() == Type.ADDED) { Log.d(TAG, "New city: " + dc.getDocument().getData()); } } } });
final docRef = db.collection("cities"); docRef.snapshots().listen( (event) => print("listener attached"), onError: (error) => print("Listen failed: $error"), );
// Snippet coming soon
// Snippet coming soon.
// Not supported in the PHP client library
ListenerRegistration registration = db.Collection("cities").Listen( querySnapshot => { // ... }); registration.ListenerTask.ContinueWithOnMainThread( listenerTask => { if (listenerTask.IsFaulted) { Debug.LogError($"Listen failed: {listenerTask.Exception}"); // ... // Handle the listener error. // ... } });
// Snippet coming soon
Nächste Schritte
- Listener mit einfachen und kumulierenden Abfragen kombinieren
- Abgerufene Dokumente sortieren und beschränken
- Abrechnung für Listener