停止在颤动中收听 Cloud Firestore 中的快照更新
Posted
技术标签:
【中文标题】停止在颤动中收听 Cloud Firestore 中的快照更新【英文标题】:Stop listening to snapshot updates in cloud firestore in flutter 【发布时间】:2019-01-25 20:00:48 【问题描述】:我想停止收听快照更新。即使在屏幕关闭后,快照也会继续收听更新。我正在使用下面的代码来收听更新。
CollectionReference reference = Firestore.instance.collection('Events');
reference.snapshots().listen((querySnapshot)
querySnapshot.documentChanges.forEach((change)
// Do something with change
);
)
【问题讨论】:
【参考方案1】:您的侦听器是StreamSubscription
类型,因此您可以在侦听器上调用一些有用的方法,例如cancel()
CollectionReference reference = Firestore.instance.collection('Events');
StreamSubscription<QuerySnapshot> streamSub = reference.snapshots().listen((querySnapshot)
querySnapshot.documentChanges.forEach((change)
// Do something with change
);
);
//somewhere
streamSub.cancel();
【讨论】:
不仅在“某处”取消订阅,而且在不再需要它时,通常需要覆盖方法dispose()
,如下所示:@override void dispose() if(streamSub!= null) streamSub.cancel(); super.dispose();
那是完美的.. 但是如果您通过 StreamProvider 在 Ref 处获得更改怎么办?我将如何断开连接?还是我们无法处理?【参考方案2】:
listen
方法返回一个Subscription
该类用于取消监听。
您应该在您的状态中存储该对象以在处置时取消订阅。
【讨论】:
Remi - 我已经设置了stream.listen
,但是当initState
加载屏幕时它正在侦听一次,并非总是在Firestore
上添加/更改某些内容时。请在***.com/questions/68052839/… 检查问题并建议我。非常感谢。
对如何使用 Riverpod 执行此操作有任何想法吗?现在坐了 4 天,无法取消听众。 Flutter 和 Firestore 都不会在导航时取消它们。【参考方案3】:
很晚的答案,但我想我会用代码示例完成以前的答案,因为它可能对其他人有用。
class EventsScreen extends StatefulWidget
EventsScreen(Key key) : super(key: key);
@override
_EventsScreenState createState() => _EventsScreenState();
class _EventsScreenState extends State<EventsScreen>
StreamSubscription<QuerySnapshot> _eventsSubscription;
@override
void initState()
// Initialise your stream subscription once
CollectionReference eventsReference = Firestore.instance.collection('Events');
_eventsSubscription = eventsReference.snapshots().listen((snapshot) => _onEventsSnapshot);
super.initState();
@override
Widget build(BuildContext context)
// Build your widget here
return Container();
void _onEventsSnapshot(QuerySnapshot snapshot)
// Remove the setState() call if you don't want to refresh your screen whenever you get a fresh snapshot
setState(()
snapshot?.documentChanges?.forEach(
(docChange) =>
// If you need to do something for each document change, do it here.
,
);
// Anything you might do every time you get a fresh snapshot can be done here.
);
@override
void dispose()
// Cancel your subscription when the screen is disposed
_eventsSubscription?.cancel();
super.dispose();
这种方法利用 StatefulWidget 的状态来处理文档更改。
更好的方法是使用 Provider 或 BLoC pattern,这样就不会在 UI 中创建和处理对 Firestore 的订阅。
【讨论】:
很好的答案。我的问题是 - 如果我确实使用 Provider... 我将如何取消收听?至少在这里我有一个 subscription.cancel() 方法......知道吗?或者您不认为在不需要时持续收听会不必要地消耗资源吗? 解决了吗?我正在使用 redux 并且有 UI -> Thunk 中间件 -> 服务层。我的监听器在中间件层的方法调用中。如何调用一个操作来取消在不同方法中的订阅。 @JLP-Dev JLP-Dev,我已将listen
设置为Firestore snapshots()
,但在调用listen
函数时遇到问题。您能否通过***.com/questions/68052839/…查看并建议我,非常感谢。
有没有人在如何使用 Riverpod/Provider 取消监听器方面取得进展?我就是做错了,已经有 4 天的压力了。听众根本不会被自己取消。【参考方案4】:
正确的方法是stream.pause() 所以监听器将处于暂停模式 cancel() 销毁监听器和他的内容
【讨论】:
【参考方案5】:对我来说,我只是在快照方法上使用take。基本上,与 rxjs 与 Firebase 的原理相同。您获取一个数据流并停止收听。
return collection
.withConverter<Discount>(
fromFirestore: (snapshots, _) => Discount.fromMap(snapshots
.data()!),
toFirestore: (discount, _) => discount
.toMap(),
)
.snapshots()
.take(1); // Take 1 to stop listening to events
如果您运行并打印出 ConnectionState,您会看到它在获取集合中的所有文档后进入 Done。
【讨论】:
以上是关于停止在颤动中收听 Cloud Firestore 中的快照更新的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Cloud Firestore 在颤动中设置参考选择数组的位置条件 [关闭]
将 DateTime 序列化为时间戳以用于 Firestore 颤动
如何在颤动中收听 UIApplication 生命周期 iOS