首页 > 解决方案 > 为 ListView 异步构建小部件的颤振问题

问题描述

我想从 Firestore 查询图像并将它们显示在我的应用程序中。使用以下代码显示一张图像可以很好地工作:

Future<Widget> _getImage(BuildContext context) async {
    try {
      Image img;
      await FireStorageService.loadImage(context,
          '/Stände/' + standName + '/' + currentDate + '/hallo.jpg')
          .then((downloadUrl) {
        img = Image.network(
          downloadUrl.toString(),
          fit: BoxFit.scaleDown,
        );});
        return img;     
    } catch (err) {
      print(err);
    }
  }

  static Future<dynamic> loadImage(BuildContext context, String image) async {
    return await FirebaseStorage.instance.ref().child(image).getDownloadURL();
  }


        child: FutureBuilder(
          future: _getImage(context),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.done)
              return SingleChildScrollView(
                child: Column(
                  children: <Widget>[
                    Container(
                      height: MediaQuery.of(context).size.height / 1.25,
                      width: MediaQuery.of(context).size.width / 1.25,
                      child: snapshot.data,
                    ),
                  ],
                ),
              );
            if (snapshot.connectionState == ConnectionState.waiting)
              return Container(
                  height: MediaQuery.of(context).size.height / 1.25,
                  width: MediaQuery.of(context).size.width / 1.25,
                  child: CircularProgressIndicator());

            return Container(child: Text('some error'));
          },
        ),
      ),

如果我将我的图像创建包装在一个循环中,它不会显示任何内容。我没有收到任何错误消息,如果我打印存储小部件的列表,它会显示我的图像,它们只是没有显示在屏幕上。

Future<Widget> _getImage(BuildContext context) async {
    try {
      CollectionReference _documentRef = Firestore.instance
          .collection('Stände')
          .document('Testing')
          .collection(currentDate)
          .document(standName)
          .collection('images');
      Image img;
      List<Widget> imgList = [];
      _documentRef.getDocuments().then((ds) {
        ds.documents.forEach((value) async{
          await FireStorageService.loadImage(context,
                  '/Stände/' + standName + '/' + currentDate + '/hallo.jpg')
              .then((downloadUrl) {
            img = Image.network(
              downloadUrl.toString(),
              fit: BoxFit.scaleDown,
            );
            imgList.add(img);
          });
          print('${imgList}');
          return ListView.builder(
              itemCount: imgList.length,
              itemBuilder: (context, index) {
                return imgList[index];
              });
        });
      });
    } catch (err) {
      print(err);
    }
  }

我怀疑是异步循环造成了问题:

      _documentRef.getDocuments().then((ds) {
        ds.documents.forEach((value) async{

但我只是不明白为什么它不起作用。高度赞赏帮助!

标签: firebaseflutterdartgoogle-cloud-firestore

解决方案


您正在 forEach 函数内部返回。_getImage 实际上什么也没返回。

Future<Widget> _getImage(BuildContext context) async {
  try {
    // ...
    ds = await _documentRef.getDocuments();
    for (var doc in ds) {
      var downloadUrl = await FireStorageService.loadImage(
         context,
         '/Stände/' + standName + '/' + currentDate + '/hallo.jpg',
      );
      img = Image.network(
        downloadUrl.toString(),
        fit: BoxFit.scaleDown,
      );
      imgList.add(img);
    }

    // Now function is returning a widget
    return ListView.builder(
      itemCount: imgList.length,
      itemBuilder: (context, index) {
        return imgList[index];
      },
    );
  } catch (error) {
    // Error handing
  }
}

推荐阅读