Flutter中的StreamBuilder卡在ConnectionState.waiting状态,仅显示加载标记。

8

你好,我正在尝试动态地将Firebase文档中的数据显示在我的Flutter应用中,使用循环进行渲染。因此,我创建了一个 List<Widget> Cards 并添加了函数 makeItem() 来包含卡片,并将它们放入一个循环中。问题是当我运行代码时,始终以 ConnectionState.waiting 输出 print(snapshot.connectionState);,而它应该是异步快照,但它拒绝按需加载数据。我应该提到的是,当我点击“Android Studio中的热重载”时,数据会按所需显示。

所以我不知道如何解决这个问题。谢谢!


请选一个答案并将其标记为“已接受”;我们这里不使用任何“已解决”。 - Martin Zeitler
我刚刚发布了它,需要22个小时才能将答案标记为已接受,所以我不得不写“已解决”,因为这是许多开发人员处理的错误。 - AdnanAsali
你可以用这22个小时来提供一个适当的答案,而不是你已经被投票反对了的仅包含一个链接的回答,它实际上并没有尝试回答问题。 - Martin Zeitler
1
它为我解决了错误,我按照文档中的说明进行操作,在经过多天的尝试后终于成功了 :) 那么你的问题是什么,朋友? - AdnanAsali
我没有问题,但是你的回答有问题。请查看下面“链接到答案”中的何时将答案标记为“不是答案”?希望这能解释清楚;显然还有改进的空间。 - Martin Zeitler
请使用FutureBuilder,它解决了我的问题。 - Riddhi Shankar
4个回答

4

在使用流创建器(stream builder)和提供者(provider)&变更通知(change notifier)时,我遇到了同样的问题。

返回视图时,应重新分配流本身。

为您的流制作一个获取函数,在该函数中,在返回流之前重新分配流。这解决了我的加载问题。


你能给我们举个例子吗?谢谢。 - Wege

2
你可以尝试以下操作吗?
class MyList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: _firestore.collection(widget.city).snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (snapshot.hasError)
          return Text('Error: ${snapshot.error}');
        switch (snapshot.connectionState) {
          case ConnectionState.waiting: return Center(child: CircularProgressIndicator(backgroundColor: Colors.amber,strokeWidth: 1),),
          default:
            return ListView(
              children: snapshot.data.documents.map((DocumentSnapshot document) {
                return makeItem(
                  pointName: document['name'],
                  huge: document['lastname'],
                  moderate: document['mobileNumber'],
                  none: document['location'],
                  fights: document['job'],
               );
              }).toList(),
           );
        }
      },
    );
  }
}

谢谢您的回复,但是没有起作用,输出结果相同,o ho reload 显示了结果。 - AdnanAsali
1
你能分享一下makeItem()函数吗?顺便说一句,我建议你返回一个widget而不是一个widget构建函数。这样更有效率。你可以创建一个带有final参数的Stateless Widget并返回它。 - Can
我添加了makeItem函数,将widget作为类更高效,虽然一开始它只是一个小部件,我打算将其返回到一个函数中,但现在它变得越来越大了。 但我认为,在Stream Builder上使用widget类不会有任何区别。 - AdnanAsali
好的,让我们进行一个简单的测试。你能试着返回一个文本小部件吗? 不要使用makeItem,而是返回Text(document['name'])。 - Can
实际上问题出在流构建器上,连接状态是“等待”。一旦连接激活并获取数据,一切就会正常。等我使用文本小部件而不是makeItem。 - AdnanAsali
显示剩余3条评论

2

我想我有东西可以让你试试。在我的模拟器上有效。

List<Widget> cards = [];
  Stream<QuerySnapshot> firebaseStream;

  @override
  void initState() {
    super.initState();
    firebaseStream = Firestore.instance.collection('Hearings').snapshots();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: StreamBuilder<QuerySnapshot>(
          stream: firebaseStream,
          builder: (BuildContext context,
              AsyncSnapshot<QuerySnapshot> asyncSnapshot) {
            List<DocumentSnapshot> snapData;

            if (asyncSnapshot.connectionState == ConnectionState.waiting) {
              return Container(
                child: Center(
                  child: CircularProgressIndicator(
                    backgroundColor: Colors.amber,
                    strokeWidth: 1,
                  ),
                ),
              );
            } else if (asyncSnapshot.connectionState ==
                ConnectionState.active) {
              snapData = asyncSnapshot.data.documents;
              if (asyncSnapshot.hasData) {
                for (int i = 0; i < snapData.length; i++) {
                  Widget card = Text(snapData[i].data['locationName']);

                  cards.add(card);
                }
              }
            }
            return ListView.builder(
              itemCount: cards.length,
              itemBuilder: (context, index) => cards[index],
            );
          },
        ),
      ),
    );

不过,我也有坏消息。现在数据正在更新,它暴露了您逻辑中的一些缺陷,它会在数组中复制旧条目。您会看到的。不过这应该很容易修复。


1
嘿,谢谢你的回复, 我试过了,实际上它没有起作用,所以我尝试在initState之外初始化firestream,它工作了几次并写入了“ConnectionState.active”,然后又失败了并显示“ConnectionState.waiting”,这真的很有趣,你认为我应该使用“Future.delayed(Duration())”吗? - AdnanAsali
1
我无法在我的端上重现这个问题,即使在第15个输入后仍然接受数据。很抱歉它在initState()中不起作用,但对我来说也是可以的,哈哈。我想知道问题是否来自其他地方,但我不知道它可能在哪里。至于未来,您需要向我解释为什么您认为需要使用它,或者提供一些参考文献,说明有人建议在这种情况下使用它。据我所知,您不应该使用它。 - wcyankees424
没问题,非常感谢你的努力,我很感激。你觉得我应该在一个简单的 get 函数中获取数据,然后放置一个实时监听器在卡片上,在 firebase 中进行 onChange 更新吗? - AdnanAsali
1
如果这个方法有效的话,那就是一个不错的解决办法,因为其他人也遇到了和你一样的问题。值得一试。 - wcyankees424
1
很好,我会去检查它。 - wcyankees424
显示剩余3条评论

0
使用StreamBuilder上的stream.cast()解决了我的问题。

这更适合作为对问题的评论,而不是答案,因为它非常简短。 - Phani Rithvij

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接