我正在构建一个包含讨论线程的应用程序。每个线程都有一个回复子集合,每个回复都有一个这样的反应图。因此,如果 JSON 化,每个 Thread 的子集合将如下所示:
{
'replyDocument1': {
'authorName': 'Steve Dave',
'text': 'this is a reply',
'reactions': {'': ['userid1', 'userid2']}
},
...
}
我正在尝试使用 Stream/Sink 设置来收听 Replies 子集合中的更改。即:只要有人向子集合中的任何回复添加反应,就重建回复列表视图。
这就是我到目前为止所得到的。模型和 RepliesApi 类没有做任何令人兴奋的事情,所以我将它们排除在外。
class RepliesBloc {
final String threadId;
RepliesApi _api;
final _controller = StreamController<List<Reply>>.broadcast();
Stream<List<Reply>> get stream =>
_controller.stream.asBroadcastStream();
StreamSink<List<Reply>> get sink => _controller.sink;
RepliesBloc(this.threadId) {
this._api = RepliesApi(this.threadId);
this
._api
.collectionReference
.getDocuments()
.asStream()
.listen(_repliesUpdated);
this._api.collectionReference.snapshots().listen(_repliesUpdated);
}
void _repliesUpdated(QuerySnapshot querySnapshot) {
List<Reply> replies = _api.fromQuerySnapshot(querySnapshot);
this.sink.add(replies);
}
void dispose() {
_controller.close();
}
}
class ThreadReplyList extends StatefulWidget {
ThreadReplyList(this.threadId, {Key key}) : super(key: key);
final String threadId;
@override
_ThreadReplyListState createState() => _ThreadReplyListState();
}
class _ThreadReplyListState extends State<ThreadReplyList> {
RepliesBloc _bloc;
@override
void initState() {
super.initState();
this._bloc = RepliesBloc(this.widget.threadId);
}
@override
Widget build(BuildContext context) {
dev.log('starting ThreadReplyList.build', name: "ThreadReplyList.build");
return StreamBuilder(
stream: this._bloc.stream,
builder: (context, snapshot) {
return ListView.separated(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ThreadReply(snapshot.data[index]);
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox.shrink();
},
);
});
}
}
这可以很好地加载初始数据,如果我更改集合,例如:添加或删除回复,ListView 会重建。但是,如果我修改回复,例如:reactions
在单个回复上更新地图,则不会发生任何事情。
我已经看到了向 QuerySnapshot 中的每个文档添加侦听器的解决方案,但我不清楚如何在这里实现它。