我遇到了一个奇怪的问题,其中加载从MultiImagePicker转换的文件仅在热重新加载页面后才成功加载,否则它将返回以下错误:
未处理的异常:无法加载资产:/storage/emulated/0/DCIM/Camera/IMG_20191105_104542.jpg
步骤:
initState从Firestore加载现有的图像字符串,这些字符串通过DefaultCacheManager缓存到File,并添加到tmpGalleryImages列表中。
添加图像使用MultiImagePicker,然后将其从Asset转换为File并添加到tmpGalleryImages列表。
我创建了一个SetState按钮来测试重新加载状态,但是在调用SetState之后仍然出现上述错误-所以我非常困惑为什么它只有在热重新加载后才能正常工作?
注意:通过转换为文件的麻烦,我可以将本地图像(资产)和Firestore图像(字符串)组合到一个列表中,可以对其进行编辑并重新上传到Firestore < / p>
initState:
@override
void initState() {
super.initState();
setState(() {
_galleryBloc.getGalleryImages(
docRef: Firestore.instance.collection("galleries").document("gal_${widget.docId}"),
tmpGalleryImages: widget.tmpGalleryImages,
callback: widget.callback);
});
}
StreamBuilder:
@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();
},
),
BLOC:
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;
}
答案 0 :(得分:1)
请勿使用 rootBundle 打开未通过pubspec.yaml与应用程序打包在一起的文件。用File类打开它们。
rootBundle包含与 构建时的应用程序。要将资源添加到rootBundle中 您的应用程序,将它们添加到flutter的Assets小节中 应用程序的pubspec.yaml清单的一部分。