【问题标题】:StreamBuilder hangs when listening to Firestore snapshotStreamBuilder 在监听 Firestore 快照时挂起
【发布时间】:2019-03-26 21:20:13
【问题描述】:

复制步骤

我正在尝试将 bloc 模式与 firebase 一起使用,但由于没有使用 firebasebloc pattern 的好的教程,因此遇到了困难。

我在做这件事的时候遇到了奇怪的事情,努力找出问题,但没有找到。

我已经创建了UserBloc,并在听完Firestore snapshot之后尝试设置UserModel

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 的构造函数中进行监听和设置数据。我不知道为什么会这样。

【问题讨论】:

标签: firebase flutter google-cloud-firestore subscription


【解决方案1】:

我认为您在使用 Streambuilder 时必须删除 Bloc 中流控制器的监听语句。因为Streambuilder在Bloc中监听流控制器,所以Streambuilder和Bloc中的listen-sentence存在重复问题。

【讨论】:

    【解决方案2】:

    问题是,.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);
    

    它将向任何新侦听器重播发出的值,直到给定 [最大尺寸]。

    【讨论】:

      猜你喜欢
      • 2021-06-16
      • 2018-06-09
      • 2019-10-28
      • 2019-07-23
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 1970-01-01
      相关资源
      最近更新 更多