【问题标题】:Flutter error : The argument type 'List<Future<Widget>>' can't be assigned to the parameter type 'List<Widget>'Flutter 错误:无法将参数类型“List<Future<Widget>>”分配给参数类型“List<Widget>”
【发布时间】:2021-06-04 04:10:50
【问题描述】:

我正在尝试从 Firebase Firestore 列出项目(已完成),并为每个项目从 Firebase Cloud Storage 获取不同的图像 URL。

我使用一个名为 getPhotoUrl 的函数来更改变量 photoUrl 的值。问题是 returngetPhotoUrl 之前执行。如果我在函数 getPhotoUrl 之前添加 await 并在 _docs.map((document) 之后添加 async,我收到一个错误,提示 参数类型“List”不能分配给参数类型“List”

我的代码:

class PhotosList extends StatefulWidget {
  @override
  _PhotosListState createState() => _PhotosListState();
}

class _PhotosListState extends State<PhotosList> {
  String photoUrl = 'lib/assets/default-image.png';
  List<DocumentSnapshot> _docs;

  getPhotoUrl(documentID) {
    Reference ref = storage
        .ref('Users')
        .child(currentUser.uid)
        .child('Photos')
        .child(documentID)
        .child('image_1.jpg');
    ref.getDownloadURL().then((value) {
      setState(() {
        photoUrl = value.toString();
      });
    }).catchError((e) {
      setState(() {
        print(e.error);
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: firestore
          .collection('Users')
          .doc(currentUser.uid)
          .collection('Photos')
          .orderBy('date')
          .snapshots(),
      builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
        if (!snapshot.hasData) return CircularProgressIndicator();
        _docs = snapshot.data.docs;
        if (_docs.isEmpty)
          return Center(
              child: Text("The list is empty."));
        return Container(
          child: ResponsiveGridList(
            desiredItemWidth: 100,
            squareCells: true,
            minSpacing: 5,
            children: _docs.map((document) {
              getPhotoUrl(document.id);
              return PhotosListItem(photoUrl: photoUrl);
            }).toList(),
          ),
        );
      },
    );
  }
}

【问题讨论】:

    标签: flutter dart future


    【解决方案1】:

    我认为你混合了两种不同的方式。在每个构建循环中,您映射您的文档并请求该 photoUrl,但在该方法中您调用 setState,它会重新触发您的构建方法。这样你应该在获取照片 url 和构建你的小部件的无限循环中结束。

    您有三个选择:

    1. 加载您的 photoUrls 并将它们存储在您的小部件中 -> 调用 set state -> 检查您的映射函数是否已加载您的照片,如果是,请获取,如果不是,请调用您的 getPhotoUrl 函数
    2. 同步加载您的 photoUrls 并从您的函数返回 url 并将其设置为您的 PhotosListItem
    3. (我更喜欢这个)将您的 documentId 添加到您的映射函数中的 photosListItem 中,并在您的项目中加载此照片 url。在此 PhotoListItem 中,您的 imageUrl 有一个变量,在 initState 中您调用 getPhotoUrl 函数

    在您的 PhotoItem 内:

      String imageUrl;
      
      @override
      void initState() {
        Future.delayed(Duration.zero, () {
          setState(() {
            // load your data and set it to your variable
            imageUrl = ..
          });
        });
        super.initState();
      }
    

    【讨论】:

      【解决方案2】:

      您可能会使用 FutureBuilder,因为 StreamBuilder 似乎是同步的:

      How to convert Future<List> to List in flutter?

      【讨论】:

        【解决方案3】:

        感谢各位的回答,其实我找到了另一种解决方案,即在将图像上传到存储后直接在 Firestore 中获取和写入 URL。

        这篇文章对我帮助很大:https://medium.com/swlh/uploading-images-to-cloud-storage-using-flutter-130ac41741b2

        (PS:自这篇文章以来,一些 Firebase 名称发生了变化,但它仍然很有帮助。)

        问候。

        【讨论】:

          猜你喜欢
          • 2020-11-20
          • 2021-07-04
          • 2021-10-24
          • 2020-04-07
          • 2019-12-06
          • 2021-08-19
          • 1970-01-01
          • 2021-09-13
          • 2021-07-06
          相关资源
          最近更新 更多