使用FutureBuilder检索元素时出现问题

时间:2019-09-02 03:36:28

标签: flutter google-cloud-firestore future

我是Flutter的新手,正在尝试在我的项目中使用FutureBuilder。我正在尝试使用Cloud Firestore中的元素列表构建ListView,因此我正在使用异步函数来获取数据,并使用FutureBuilder在加载之前为我提供一个占位符。不幸的是,当我检查snapshot.connectionState == ConnectionState.done时,该视图将在列表完全填充之前加载,并且我仅获得所需的元素之一。

我尝试实现Future.delay来尝试给列表填充时间。我还尝试了打印的方式(在下面的代码中标记),以查看是否所有元素都已从数据库中提取(它们是)。我还尝试在initState()中初始化Future,但是很可能实现错误。

class PlayersFragment extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return PlayerFragStateChanged();
  }
}

class PlayerFragStateChanged extends State<PlayersFragment> {

  Widget build(BuildContext context) {
    return
      ... //other items

      FutureBuilder(
        future: DataProvider().getPlayerList(),
        builder: (BuildContext context,
          AsyncSnapshot snapshot) {
             if (snapshot.connectionState == ConnectionState.done){
              return Expanded(
                child: ListView.builder(
                  itemBuilder: (context, position) {
                    return Padding(
                      padding:
                        const EdgeInsets.only(
                          left: 20, top: 14),
                       child: Row(
                        children: <Widget>[
                           Text(snapshot.data[position].firstName),
                          Text(snapshot.data[position].lastName),
                          Text(BoolDecider().decide(snapshot.
                              data[position].amta)),
              ),
             ],
            ),
           );
          },
         itemCount: snapshot.data.length
         ));
         } else {
          return Text('Waiting for data...');
         }


       ... //other items

     }
   }



class DataProvider {
  Firestore db = firestore();

  Future<List<MockPlayer>> getPlayerList() async {
    var result = await db.collection('Users').get();

    var dataList = List<MockPlayer>();

    result.forEach((doc) async {

      debugPrint(doc.get('First name')); //Prints EVERY name in the     database (as it should)

      dataList.add(MockPlayer(
          await doc.get('First name'),
          await doc.get('Last name'),
          await doc.get('AMTA Status'),
          await doc.get('Phone number'),
          await doc.get('email'),
          await doc.get('ID')));
    });

    return dataList;
  }
}

class BoolDecider {
  String decide(bool i) {
    if (i) {
      return 'Yes';
    } else {
      return 'No';
    }
  }
}

我希望FutureBuilder可以打印多行,但是FutureBuilder的AsyncSnapshot中列表的长度仅为一,而它的长度应该大于一。

同样,当我执行result.forEach时,它会遍历数据库的每个成员。

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:0)

问题出在您的forEach语句中。在您的future.connectionState设置为done之后,带有“异步”功能的forEach完成。这是通过替换来解决的:

result.forEach((doc) async {
      dataList.add(MockPlayer(
          await .. await .. await ..);
    });

具有:

await Future.forEach(result, (doc) async {
      dataList.add(MockPlayer(
          await .. await .. await ..);
});

另外,根据Pedantic Dart所说,您不要忘记检查以下内容: snapshot.hasData && !snapshot.hasError

答案 1 :(得分:0)

另一种有效的方法是替换

result.forEach((doc) async {
      dataList.add(MockPlayer(
          await .. await .. await ..);
    });

for(final doc in result) async {
      dataList.add(MockPlayer(
          await .. await .. await ..);
    });