[英]Flutter: Loading asset error unless hot reload (BLOC + MultiImagePicker)
我有一个奇怪的问题,加载从 MultiImagePicker 转换的文件只有在热重新加载页面后才能成功加载,否则返回以下错误:
未处理的异常:无法加载资产:/storage/emulated/0/DCIM/Camera/IMG_20191105_104542.jpg
脚步:
initState 从 Firestore 加载现有的图像字符串,这些字符串通过 DefaultCacheManager 缓存到 File 并添加到 tmpGalleryImages 列表中。
添加图像使用 MultiImagePicker,然后将其从 Asset 转换为 File 并添加到 tmpGalleryImages 列表中。
我创建了一个 SetState 按钮来测试重新加载 state,但在调用 SetState 后仍然出现上述错误 - 所以我非常困惑为什么它只能在热重载后工作?
注意:通过转换为文件的麻烦,我可以将本地图像(资产)和 Firestore 图像(字符串)合并到一个可以编辑并重新上传到 Firestore 的列表中
初始化状态:
@override
void initState() {
super.initState();
setState(() {
_galleryBloc.getGalleryImages(
docRef: Firestore.instance.collection("galleries").document("gal_${widget.docId}"),
tmpGalleryImages: widget.tmpGalleryImages,
callback: widget.callback);
});
}
流生成器:
@override
Widget build(BuildContext context) {
return StreamBuilder<List<File>>(
stream: _galleryBloc.multipleImageStream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.none) {
print("none");
}
if (snapshot.connectionState == ConnectionState.waiting) {
print("Waiting");
}
return Column(
children: <Widget>[
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 4),
itemCount: snapshot.data.length < widget.imageLimit ? snapshot.data.length + 1 : snapshot.data.length,
itemBuilder: (context, index) {
return index < snapshot.data.length
? GalleryStepperThumbnail(
file: snapshot.data[index],
onTap: () {
_showGalleryStepperOptions(
context: context,
tmpGalleryImages: snapshot.data,
imageLimit: widget.imageLimit,
file: snapshot.data[index],
fileName: "img_${index + 1}",
);
})
: snapshot.data.length < widget.imageLimit
? InkWell(
onTap: () => _showGalleryStepperOptions(
context: context,
tmpGalleryImages: snapshot.data,
imageLimit: widget.imageLimit,
fileName: "img_${index + 1}",
),
child: Card(
child: Center(
child: Icon(Icons.add),
),
),
)
: Offstage();
},
),
集团:
class GalleryBloc {
final _multipleImageController = StreamController<List<File>>.broadcast();
Stream<List<File>> get multipleImageStream => _multipleImageController.stream;
// -----------------------------------------------------------------------------
// Load existing gallery images
// -----------------------------------------------------------------------------
Future<void> getGalleryImages({DocumentReference docRef, List<File> tmpGalleryImages, Function callback}) async {
try {
await docRef.get().then(
(value) async {
if (value.data != null && tmpGalleryImages.length == 0) {
for (var img in value.data['gallery_images']) {
File fetchedFile = await DefaultCacheManager().getSingleFile(img);
tmpGalleryImages.add(fetchedFile);
}
}
},
);
} catch (e) {
print(e.toString());
}
callback(tmpGalleryImages);
_multipleImageController.sink.add(tmpGalleryImages);
}
// -----------------------------------------------------------------------------
// Convert File to Asset
// -----------------------------------------------------------------------------
Future<File> _convertAssetToFile(String path) async {
final byteData = await rootBundle.load(path);
final file = File(path);
await file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
return file;
}
// -----------------------------------------------------------------------------
// Select Multiple Images
// -----------------------------------------------------------------------------
Future<void> pickMultipleImages({List<File> tmpGalleryImages, int imageLimit, Function callback}) async {
try {
await MultiImagePicker.pickImages(
maxImages: imageLimit - tmpGalleryImages.length,
).then((chosenImages) async {
for (var path in chosenImages) {
await _convertAssetToFile(await path.filePath).then(
(convertedFile) {
tmpGalleryImages.add(convertedFile);
},
);
}
});
} on Exception catch (e) {
print(e.toString());
}
_multipleImageController.sink.add(tmpGalleryImages);
callback(tmpGalleryImages);
}
如果有人可以就我哪里出错提供一些指导,我将不胜感激!
根据 IGOR 的回答(工作)更新代码:
// -----------------------------------------------------------------------------
// Convert File to Asset
// -----------------------------------------------------------------------------
Future<File> _convertAssetToFile(String path) async {
final file = File(path);
return file;
}
不要使用rootBundle打开未通过 pubspec.yaml 与应用打包的文件。 使用文件 class 打开它们。
rootBundle 包含在构建应用程序时与应用程序一起打包的资源。 要将资源添加到应用程序的 rootBundle,请将它们添加到应用程序 pubspec.yaml 清单的 flutter 部分的 assets 子部分。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.