【问题标题】:Nesting two stream builders causing bad state error嵌套两个流构建器导致错误状态错误
【发布时间】:2020-10-12 13:01:12
【问题描述】:

我正在从两个不同的 Firestore 集合中获取数据,这是我的代码

 StreamBuilder(
           stream: Firestore.instance.collection('items').snapshots(),
           builder: (BuildContext context, snapshot){

             if(snapshot.connectionState == ConnectionState.waiting){
               return CupertinoActivityIndicator();
             }
             if(snapshot.data != null){
               return ListView.builder(
                 itemCount: snapshot.data.documents.length,
                 itemBuilder: (context,index){
                   return Column(
                     children: <Widget>[

                       Text(snapshot.data.documents[index]['name']),
                       Text(snapshot.data.documents[index]['color']),
                       Text(snapshot.data.documents[index]['lifetime']),

                       Container(
                         child: StreamBuilder(
                           stream: Firestore.instance.collection('users')
                            .document(userid).collection('Quantity')
                            .document(snapshot.data.documents[index]['id']).snapshots(),
                           builder: (BuildContext context, snap){

                             if(snapshot.connectionState == ConnectionState.waiting){
                              return CupertinoActivityIndicator();
                            }
                            if(snap.data != null){
                              return Container(
                              child:  Text(snap.data.documents.length)
                              );
                            }
                           },
                         ),
                       )

                     ],
                   );
                 });
             }
           },
         )

它给了我错误,但是当我在 streambuilder 中使用 futurebuilder 时一切正常,我也使用了流广播,但它也给了我同样的错误。 这是我用于广播流的代码

  StreamController _controller = StreamController.broadcast();
        Stream getItems() async*{
          Firestore.instance.collection('items').snapshots().listen((data){
            _controller.add(data);
          })
          yield* _controller.stream;
        }

【问题讨论】:

    标签: firebase flutter google-cloud-firestore stream-builder


    【解决方案1】:

    您不应在 StreamBuilder 内创建新的 Stream。当你这样做时:

    StreamBuilder(
      stream: Firestore.instance.collection('items').snapshots(),
    

    StreamBuilder(
      stream: Firestore.instance.collection('users')
        .document(userid).collection('Quantity')
        .document(snapshot.data.documents[index]['id']).snapshots(),
    

    每次调用build() 函数时都会创建一个新的StreamBuilder,因此会调用Firestore.instance.collection()...snapshots(),每次都返回一个新的Stream

    您应该将您的小部件转换为StatefulWidget 并在initState() 上初始化您的Stream,将其作为类变量传递给您的StreamBuilder。嵌套的StreamBuilder 也可以转换为StatefulWidget 并就地创建,但以相同的方式初始化。请注意,您可能需要Key 才能在ListView 上正确显示它。

    此外,如果您想将单个订阅 Stream 转换为广播 Stream,您只需调用 asBroadcastStream 即可进行转换。

    【讨论】:

    • 非常感谢现在一切正常,但是使用这种方法,我的代码看起来比嵌套流构建器更复杂。我仍然不明白为什么直接向流构建器提供流会出错?
    • 我认为这与共享相同上下文的 2 个 StreamBuilders 有关,因此当外部的发出时,内部的会使用相同的上下文重新创建,因此它可能正在获取对旧流的引用以进行订阅。这可能会重复到 StreamBuilder 逻辑上处理正在传递的新旧流,必须进行更深入的调查。
    猜你喜欢
    • 2021-09-29
    • 2019-07-23
    • 1970-01-01
    • 2015-01-11
    • 2015-10-20
    • 2011-09-14
    • 1970-01-01
    • 2012-06-05
    • 1970-01-01
    相关资源
    最近更新 更多