Flutter 颤振:除非热重新加载,否则加载资源错误(块和多图像选择器)
我遇到了一个奇怪的问题,加载从MultiImagePicker转换的文件仅在热重新加载页面后才能成功加载,否则返回以下错误: 未处理的异常:无法加载资产:/storage/simulated/0/DCIM/Camera/IMG_20191105_104542.jpg 步骤:Flutter 颤振:除非热重新加载,否则加载资源错误(块和多图像选择器),flutter,Flutter,我遇到了一个奇怪的问题,加载从MultiImagePicker转换的文件仅在热重新加载页面后才能成功加载,否则返回以下错误: 未处理的异常:无法加载资产:/storage/simulated/0/DCIM/Camera/IMG_20191105_104542.jpg 步骤: @override void initState() { super.initState(); setState(() { _galleryBloc.getGalleryImages( docRef: Fi
@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);
}
// -----------------------------------------------------------------------------
// Convert File to Asset
// -----------------------------------------------------------------------------
Future<File> _convertAssetToFile(String path) async {
final file = File(path);
return file;
}
@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);
}
// -----------------------------------------------------------------------------
// Convert File to Asset
// -----------------------------------------------------------------------------
Future<File> _convertAssetToFile(String path) async {
final file = File(path);
return file;
}
}
StreamBuilder:
@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);
}
// -----------------------------------------------------------------------------
// Convert File to Asset
// -----------------------------------------------------------------------------
Future<File> _convertAssetToFile(String path) async {
final file = File(path);
return file;
}
@覆盖
小部件构建(构建上下文){
返回流生成器(
流:_galleryBloc.multipleImageStream,
生成器:(上下文,快照){
if(snapshot.connectionState==connectionState.none){
打印(“无”);
}
if(snapshot.connectionState==connectionState.waiting){
打印(“等待”);
}
返回列(
儿童:[
GridView.builder(
gridDelegate:SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount:4),
itemCount:snapshot.data.length\u ShowGallerySpeoptions(
上下文:上下文,
tmpgalleryImage:snapshot.data,
imageLimit:widget.imageLimit,
文件名:“img_${index+1}”,
),
孩子:卡片(
儿童:中心(
子:图标(Icons.add),
),
),
)
:后台();
},
),
集团:
@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);
}
// -----------------------------------------------------------------------------
// Convert File to Asset
// -----------------------------------------------------------------------------
Future<File> _convertAssetToFile(String path) async {
final file = File(path);
return file;
}
class GalleryBloc{
final _multipleImageController=StreamController.broadcast();
Stream get multipleImageStream=>\u multipleImageController.Stream;
// -----------------------------------------------------------------------------
//加载现有库图像
// -----------------------------------------------------------------------------
未来的GetGalleryImage({DocumentReference docRef,List TMPGalleryImage,函数回调})异步{
试一试{
等待docRef.get(),然后(
(值)异步{
if(value.data!=null&&tmpGalleryImages.length==0){
for(var img在value.data['gallery_images']中){
File fetchedFile=await DefaultCacheManager().getSingleFile(img);
tmpgallerymages.add(fetchedFile);
}
}
},
);
}捕获(e){
打印(如toString());
}
回调(TMPGalleryImage);
_multipleImageController.sink.add(tmpgalleryImage);
}
// -----------------------------------------------------------------------------
//将文件转换为资产
// -----------------------------------------------------------------------------
Future\u convertAssetToFile(字符串路径)异步{
final byteData=wait rootBundle.load(路径);
最终文件=文件(路径);
wait file.writeAsBytes(byteData.buffer.asUint8List(byteData.offsetInBytes,byteData.lengthInBytes));
返回文件;
}
// -----------------------------------------------------------------------------
//选择多个图像
// -----------------------------------------------------------------------------
未来的pickMultipleImages({List tmpGalleryImages,int-imageLimit,Function callback})异步{
试一试{
等待MultiImagePicker.pickImages(
最大值:imageLimit-tmpGalleryImages.length,
).then((chosenImages)异步{
for(chosenImages中的变量路径){
wait_convertAssetToFile(wait path.filePath)。然后(
(转换文件){
tmpgallerymages.add(convertedFile);
},
);
}
});
}关于异常捕获(e){
打印(如toString());
}
_multipleImageController.sink.add(tmpgalleryImage);
回调(TMPGalleryImage);
}
如果有人能为我的错误提供一些指导,我将不胜感激
根据IGOR的答案更新代码(有效):
@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);
}
// -----------------------------------------------------------------------------
// Convert File to Asset
// -----------------------------------------------------------------------------
Future<File> _convertAssetToFile(String path) async {
final file = File(path);
return file;
}
//-----------------------------------------------------------------------------
//将文件转换为资产
// -----------------------------------------------------------------------------
Future\u convertAssetToFile(字符串路径)异步{
最终文件=文件(路径);
返回文件;
}
不要使用rootBundle通过pubspec.yaml打开应用程序未打包的文件。请使用File类打开它们
rootBundle包含与打包在一起的资源
应用程序生成时。将资源添加到rootB