获取实时更新
您可以使用 onSnapshot() 方法监听某个文档。在对您提供的回调函数进行初始调用后,系统将立即创建一份文档快照,其中包含文档的当前内容。之后,每次内容发生更改时,另一次调用将更新文档快照。
Web
import { doc, onSnapshot } from "firebase/firestore";
const unsub = onSnapshot(doc(db, "cities", "SF"), (doc) => {
console.log("Current data: ", doc.data());
});
listen_document.js
Web
db.collection("cities").doc("SF")
.onSnapshot((doc) => {
console.log("Current data: ", doc.data());
});
test.firestore.js
Swift
注意:此产品不适用于 watchOS 和 App Clip 目标。
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)")
}
ViewController.swift
Objective-C
注意:此产品不适用于 watchOS 和 App Clip 目标。
[[[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);
}];
ViewController.m
Kotlin
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")
}
}
DocSnippets.kt
Java
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");
}
}
});
DocSnippets.java
Dart
final docRef = db.collection("cities").doc("SF");
docRef.snapshots().listen(
(event) => print("current data: ${event.data()}"),
onError: (error) => print("Listen failed: $error"),
);
firestore.dart
通常情况下,您需要让界面对 Firestore 文档或集合内容的变化做出反应。您可以借助处理 Firestore 快照流的 StreamBuilder widget 来实现此目的:
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(),
);
},
);
}
}
user_info_streambuilder.dart
Java
DocumentReference docRef = db.collection("cities").document("SF");
docRef.addSnapshotListener(
new EventListener<DocumentSnapshot>() {
@Override
public void onEvent(@Nullable DocumentSnapshot snapshot, @Nullable FirestoreException e) {
if (e != null) {
System.err.println("Listen failed: " + e);
return;
}
if (snapshot != null && snapshot.exists()) {
System.out.println("Current data: " + snapshot.getData());
} else {
System.out.print("Current data: null");
}
}
});
ListenDataSnippets.java
Python
# Create an Event for notifying main thread.
callback_done = threading.Event()
# Create a callback on_snapshot function to capture changes
def on_snapshot(doc_snapshot, changes, read_time):
for doc in doc_snapshot:
print(f"Received document snapshot: {doc.id}")
callback_done.set()
doc_ref = db.collection("cities").document("SF")
# Watch the document
doc_watch = doc_ref.on_snapshot(on_snapshot)
snippets.py
C++
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;
}
});
snippets.cpp
Node.js
const doc = db.collection('cities').doc('SF');
const observer = doc.onSnapshot(docSnapshot => {
console.log(`Received doc snapshot: ${docSnapshot}`);
// ...
}, err => {
console.log(`Encountered error: ${err}`);
});
index.js
Go
import (
"context"
"fmt"
"io"
"time"
"cloud.google.com/go/firestore"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
// listenDocument listens to a single document.
func listenDocument(ctx context.Context, w io.Writer, projectID, collection string) error {
// projectID := "project-id"
// Сontext with timeout stops listening to changes.
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
client, err := firestore.NewClient(ctx, projectID)
if err != nil {
return fmt.Errorf("firestore.NewClient: %w", err)
}
defer client.Close()
it := client.Collection(collection).Doc("SF").Snapshots(ctx)
for {
snap, err := it.Next()
// DeadlineExceeded will be returned when ctx is cancelled.
if status.Code(err) == codes.DeadlineExceeded {
return nil
}
if err != nil {
return fmt.Errorf("Snapshots.Next: %w", err)
}
if !snap.Exists() {
fmt.Fprintf(w, "Document no longer exists\n")
return nil
}
fmt.Fprintf(w, "Received document snapshot: %v\n", snap.Data())
}
}
listen_document.go
PHP
// Not supported in the PHP client library
Unity
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));
}
});
C
DocumentReference docRef = db.Collection("cities").Document("SF");
FirestoreChangeListener listener = docRef.Listen(snapshot =>
{
Console.WriteLine("Callback received document snapshot.");
Console.WriteLine("Document exists? {0}", snapshot.Exists);
if (snapshot.Exists)
{
Console.WriteLine("Document data for {0} document:", snapshot.Id);
Dictionary<string, object> city = snapshot.ToDictionary();
foreach (KeyValuePair<string, object> pair in city)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}
}
});
Program.cs
Ruby
doc_ref = firestore.col(collection_path).doc document_path
snapshots = []
# Watch the document.
listener = doc_ref.listen do |snapshot|
puts "Received document snapshot: #{snapshot.document_id}"
snapshots << snapshot
end
query_watch
.rb
