由于没有好的教程使用firebase
和bloc pattern
,因此我尝试在Firebase中使用bloc模式,并且遇到了麻烦。
在执行此操作时,我遇到了奇怪的事情,并努力找出问题所在,但未能成功。
我已经创建了UserBloc
,并在听完UserModel
之后尝试设置Firestore snapshot
。
class UserBloc extends Object {
final _user = StreamController<UserModel>.broadcast();
final _uid = StreamController<String>.broadcast();
Stream<UserModel> get user => _user.stream;
Stream<String> get uid => _uid.stream;
Function(UserModel) get setUser => _user.sink.add;
Function(String) get setUID => _uid.sink.add;
Stream<DocumentSnapshot> userStream;
UserBloc() {
uid.listen((uid) {
print('user : $uid');
if (uid != null) {
fromUID(uid);
}
});
}
fromUID(String uid) {
print('fromUID');
userStream = Firestore.instance.collection('users').document(uid).snapshots();
/// works ok when I delete below subscription
userStream.listen((data) {
});
}
dispose() {
_user.close();
_uid.close();
}
}
然后,我在小部件内使用了StreamBuilder
,如下所示。
StreamBuilder(
stream: userBloc.userStream,
builder: (context, snapshot) {
print(snapshot.connectionState);
print(snapshot.data);
return Text('testing');
},
);
问题是 snapshot.connectionState**
始终是** waiting
。但是,当我删除订阅代码userStream.listen((data) {
时,我可以使它工作。所有示例都进行侦听并在bloc
的构造函数中设置数据。我不知道为什么会这样。
答案 0 :(得分:0)
我认为您在使用Streambuilder时必须删除Bloc中流控制器的侦听语句。由于Streambuilder是Bloc中的侦听流控制器,因此Streambuilder和Bloc中的侦听语句之间存在重复问题。
答案 1 :(得分:0)
问题是.snapshot()
返回BroadcastStream。
https://www.dartlang.org/articles/libraries/broadcast-streams
第一次订阅(构造函数中的.listen
)之后,该流处于活动状态,并且在数据可用/更改时调用了onData回调。
当UI订阅流时,该流已经处于活动状态(读取操作已完成),因此 ConnectionState将始终返回等待状态,直到下一次文档更新为止。
尝试像这样修改您的代码,以重现:
/// works ok when I delete below subscription
userStream.listen((data) => print(data));
Future.delayed(Duration(seconds: 5),
() => userStream.listen((onData) => print(onData))
);
第二个回调将不触发。
为避免这种情况,您必须进行一些缓存。
将rxdart添加到您的依赖项中 https://pub.dev/packages/rxdart
像这样修改代码
userStream = Observable(Firestore.instance.collection('users').document(uid).snapshots())
.shareReplay(maxSize: 1);
它将重播发出的值给任何新的侦听器,直到给定 [maxSize]。