Flutter 错误:无法将参数类型“List<Future<Widget>>”分配给参数类型“List<Widget>”

Posted

技术标签:

【中文标题】Flutter 错误:无法将参数类型“List<Future<Widget>>”分配给参数类型“List<Widget>”【英文标题】:Flutter error : The argument type 'List<Future<Widget>>' can't be assigned to the parameter type '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(),
          ),
        );
      ,
    );
  

【问题讨论】:

【参考方案1】:

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

您有三个选择:

    加载您的 photoUrls 并将它们存储在您的小部件中 -> 调用 set state -> 检查您的映射函数是否已加载您的照片,如果是,请获取,如果不是,请调用您的 getPhotoUrl 函数 同步加载您的 photoUrls 并从您的函数返回 url 并将其设置为您的 PhotosListItem (我更喜欢这个)将您的 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 名称发生了变化,但它仍然很有帮助。)

问候。

【讨论】:

以上是关于Flutter 错误:无法将参数类型“List<Future<Widget>>”分配给参数类型“List<Widget>”的主要内容,如果未能解决你的问题,请参考以下文章

Flutter中的参数类型“String”无法分配给参数类型“Uri”[重复]

Flutter SQLlite 参数类型“Future<String>”无法分配给参数类型“String”错误

错误:无法将参数类型“MaterialAccentColor”分配给参数类型“MaterialColor”

flutter error:参数类型'Future '无法分配给参数类型'小部件'

Flutter - 错误:参数类型'String/*1*/'不能分配给参数类型'String/*2*/'

Flutter“此函数的返回类型为void,无法使用”