首页 > 解决方案 > StreamBuilder ListView 在首次加载时从 Firestore 返回空列表

问题描述

在我作为注册过程的一部分构建的应用程序中,为每个“用户”文档创建了一个子集合,其中包含多达 100 个文档。

我试图在StreamBuilder.

我有一个无法解决的奇怪错误。当StreamBuilder用户第一次查看数据时,它不会显示数据。相反,它返回一个空列表。

我可以看到文档已在子集合中正确生成。数据正在使用 StreamBuilder 的页面之前的页面上设置。即使有延迟,我也会认为新文档会刚刚开始出现在StreamBuilder. Firebase 控制台视图

如果应用程序重新启动,或者用户注销并再次登录,StreamBuilder会按预期显示数据。

下面是我正在使用的代码:

Stream<QuerySnapshot> provideActivityStream() {
    return Firestore.instance
        .collection("users")
        .document(widget.userId)
        .collection('activities')
        .orderBy('startDate', descending: true)     
        .snapshots();
  }
...
Widget activityStream() {
  return Container(
      padding: const EdgeInsets.all(20.0),
      child: StreamBuilder<QuerySnapshot>(
      stream: provideActivityStream(),
      builder: (BuildContext context,
          AsyncSnapshot<QuerySnapshot> snapshot) {
        if (snapshot.hasError)
          return new Text('Error: ${snapshot.error}');
        if(snapshot.data == null) {
          return CircularProgressIndicator();
        }
        if(snapshot.data.documents.length < 1) {
          return new Text(
            snapshot.data.documents.toString()
            );
        }
        if (snapshot != null) {
          print('$currentUser.userId');
        }
        if (
          snapshot.hasData && snapshot.data.documents.length > 0
          ) {
          print("I have documents");
          return new ListView(
              children: snapshot.data.documents.map((
                  DocumentSnapshot document) {
                  return new PointCard(
                    title: document['title'],
                    type: document['type'],
                  );
                }).toList(),
            );
        }
      } 
    )
  );
}

编辑:根据评论请求添加主构建

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: Text("Home"),
          actions: <Widget>[
          ],
          bottom: TabBar(
            tabs: [
              Text("Account"),
              Text("Activity"),
              Text("Links"),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            accountStream(),
            activityStream(),
            linksStream()
            ]
          )
        ),
      );
    }
  }

我已经尝试解决

我最初以为是连接错误,所以创建了一系列基于switch (snapshot.connectionState). 我可以看到,ConnectionState.active = true因此认为在 Firestore 中添加新文档可能会产生效果,但什么也没做。

我尝试了以下方法来使初始流构造函数异步。它无法加载任何数据。

Stream<QuerySnapshot> provideActivityStream() async* {
    await Firestore.instance
        .collection("users")
        .document(widget.userId)
        .collection('activities')
        .orderBy('startDate', descending: true)     
        .snapshots();
  }

我试过删除 tabcontroller 元素——例如只有一个页面——但这也无济于事。

我尝试使用 aDocumentSnapshot和 a访问数据QuerySnapshot。我两个都有问题。

我敢肯定这很简单,但坚持下去。非常感谢任何帮助。谢谢!

标签: flutterdartgoogle-cloud-firestorestream-builder

解决方案


它不是通过使用任何一个查询快照和文档快照来获取的

您应该首先使用 Querysnapshot 进行查询,然后将信息检索到 Documentsnapshot 是的,加载文档可能需要几秒钟 解决方案是正确的,您应该使用 async 和 await 函数

我建议你使用 Direct snapshot 而不是 streamBuilder

当您的类是 statefullWidget 并且问题也与状态有关时,我们可以在 statefullWidget 的 initstate 中加载文档快照

...

 bool isLoading;
 List<DocumentSnapshot> activity =[];
 QuerySnapshot user;
 @override
 void initState() {
  print("in init state");
  super.initState();
  getDocument();
 ``    } 
  getDocument() async{

 setState(() {
   isLoading = true;
 });
 user= await Firestore.instance
    .collection("users")
    .document(widget.userId)
    .collection('activities')
    .orderBy('startDate', descending: true)     
    .getDocuments();

  activity.isEmpty ? activity.addAll(user.documents) : null;

    setState(() {
  isLoading = false;
       });

     }

//inside  Widget build(BuildContext context) { return  Scaffold( in your body 
//section of scaffold in the cointainer
Container(
padding: const EdgeInsets.all(20.0),
child: isLoading ?
         CircularProgressIndicator(),
        :ListView.builder(

                          itemCount: global.category.length,
                          itemBuilder: (context, index) {
                            return  PointCard(
                                    title: activity[index].data['title'],
                                      type: activity[index].data['type'],
                                    );//pointcard
                             }
                            ),//builder
                     ),//container

推荐阅读