Flutter error : The argument type 'List<Future<Widget>>' can't be assigned to the parameter type 'List<Widget>'
Flutter error : The argument type 'List<Future<Widget>>' can't be assigned to the parameter type 'List<Widget>'
我正在尝试从 Firebase Firestore 中创建项目列表(已完成)并从 Firebase 云存储中为每个项目获取不同的图像 URL。
我使用名为 getPhotoUrl 的函数来更改变量 photoUrl 的值。问题是 return 在 getPhotoUrl 之前执行。如果我在函数 getPhotoUrl 前面添加 await 并在 [= 之后添加 async 35=]((document), 我得到一个错误说 参数类型 'List<Future>' 不能分配给参数类型 '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(),
),
);
},
);
}
}
我认为你混合了两种不同的方式。在每个构建循环中,您映射您的文档并请求该 photoUrl,但在该方法中您调用 setState,它会重新触发您的构建方法。这样你应该在获取照片 url 和构建你的小部件的无限循环中结束。
您有三个选择:
- 加载你的 photoUrls 并将它们存储在你的小部件中 -> 调用设置状态 -> 如果你的照片已加载,请检查你的映射函数,如果是,则获取它,如果没有,调用你的 getPhotoUrl 函数
- 同步加载您的 photoUrls 并从您的函数 return 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();
}
您可能会使用 FutureBuilder,因为 StreamBuilder 似乎是同步的:
谢谢大家的回答,其实我找到了另一种解决方案,就是在将图像上传到存储后直接在 Firestore 中获取和写入 URL。
这篇文章对我帮助很大:https://medium.com/swlh/uploading-images-to-cloud-storage-using-flutter-130ac41741b2
(PS:一些 Firebase 名称自本文发布后发生了变化,但它仍然有用。)
此致。
我正在尝试从 Firebase Firestore 中创建项目列表(已完成)并从 Firebase 云存储中为每个项目获取不同的图像 URL。
我使用名为 getPhotoUrl 的函数来更改变量 photoUrl 的值。问题是 return 在 getPhotoUrl 之前执行。如果我在函数 getPhotoUrl 前面添加 await 并在 [= 之后添加 async 35=]((document), 我得到一个错误说 参数类型 'List<Future>' 不能分配给参数类型 '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(),
),
);
},
);
}
}
我认为你混合了两种不同的方式。在每个构建循环中,您映射您的文档并请求该 photoUrl,但在该方法中您调用 setState,它会重新触发您的构建方法。这样你应该在获取照片 url 和构建你的小部件的无限循环中结束。
您有三个选择:
- 加载你的 photoUrls 并将它们存储在你的小部件中 -> 调用设置状态 -> 如果你的照片已加载,请检查你的映射函数,如果是,则获取它,如果没有,调用你的 getPhotoUrl 函数
- 同步加载您的 photoUrls 并从您的函数 return 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();
}
您可能会使用 FutureBuilder,因为 StreamBuilder 似乎是同步的:
谢谢大家的回答,其实我找到了另一种解决方案,就是在将图像上传到存储后直接在 Firestore 中获取和写入 URL。
这篇文章对我帮助很大:https://medium.com/swlh/uploading-images-to-cloud-storage-using-flutter-130ac41741b2
(PS:一些 Firebase 名称自本文发布后发生了变化,但它仍然有用。)
此致。