Você pode ouvir um documento com o método onSnapshot()
. Uma chamada inicial usando o retorno de chamada fornecido cria imediatamente um instantâneo do documento com o conteúdo atual do documento único. Então, cada vez que o conteúdo muda, outra chamada atualiza o instantâneo do documento.
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"),
);
Freqüentemente, você deseja que sua IU reaja às alterações no conteúdo de um documento ou coleção do Firestore. Você pode fazer isso com um widget StreamBuilder
que consome o fluxo de snapshot do Firestore:
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));
}
});
Eventos para mudanças locais
As gravações locais no seu aplicativo invocarão ouvintes de snapshot imediatamente. Isso se deve a um recurso importante chamado “compensação de latência”. Quando você executa uma gravação, seus ouvintes serão notificados com os novos dados antes que eles sejam enviados ao back-end.
Os documentos recuperados possuem uma propriedade metadata.hasPendingWrites
que indica se o documento possui alterações locais que ainda não foram gravadas no back-end. Você pode usar esta propriedade para determinar a origem dos eventos recebidos pelo seu ouvinte de snapshot:
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
Eventos para alterações de metadados
Ao escutar alterações em um documento, coleção ou consulta, você pode passar opções para controlar a granularidade dos eventos que seu ouvinte receberá.
Por padrão, os ouvintes não são notificados sobre alterações que afetam apenas os metadados. Considere o que acontece quando seu aplicativo grava um novo documento:
- Um evento de mudança é disparado imediatamente com os novos dados. O documento ainda não foi gravado no back-end, portanto o sinalizador "gravações pendentes" é
true
. - O documento é gravado no back-end.
- O back-end notifica o cliente sobre a gravação bem-sucedida. Não há alteração nos dados do documento, mas há uma alteração nos metadados porque o sinalizador "gravações pendentes" agora é
false
.
Se você quiser receber eventos de snapshot quando os metadados do documento ou da consulta forem alterados, passe um objeto de opções de escuta ao anexar seu ouvinte:
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
Ouça vários documentos em uma coleção
Tal como acontece com os documentos, você pode usar onSnapshot()
em vez de get()
para ouvir os resultados de uma consulta. Isso cria um instantâneo de consulta. Por exemplo, para ouvir os documentos com CA
estadual:
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);
}
});
O manipulador de instantâneo receberá um novo instantâneo de consulta sempre que os resultados da consulta forem alterados (ou seja, quando um documento for adicionado, removido ou modificado).
Ver alterações entre instantâneos
Muitas vezes é útil ver as alterações reais nos resultados da consulta entre instantâneos de consulta, em vez de simplesmente usar o instantâneo de consulta inteiro. Por exemplo, você pode querer manter um cache à medida que documentos individuais são adicionados, removidos e modificados.
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));
}
}
});
O estado inicial pode vir diretamente do servidor ou de um cache local. Se houver estado disponível em um cache local, o instantâneo da consulta será inicialmente preenchido com os dados armazenados em cache e, em seguida, atualizado com os dados do servidor quando o cliente alcançar o estado do servidor.
Desanexar um ouvinte
Quando você não estiver mais interessado em ouvir seus dados, deverá desanexar seu ouvinte para que seus retornos de chamada de evento parem de ser chamados. Isso permite que o cliente pare de usar largura de banda para receber atualizações. Por exemplo:
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();
Lidar com erros de escuta
Uma escuta pode falhar ocasionalmente — por exemplo, devido a permissões de segurança ou se você tentou escutar uma consulta inválida. (Saiba mais sobre consultas válidas e inválidas .) Para lidar com essas falhas, você pode fornecer um retorno de chamada de erro ao anexar seu ouvinte de snapshot. Após um erro, o ouvinte não receberá mais eventos e não há necessidade de desanexar o seu ouvinte.
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
Qual é o próximo
- Combine ouvintes com consultas simples e compostas .
- Ordene e limite os documentos recuperados .
- Entenda o faturamento dos ouvintes .