PickedImage 变得空
PickedImage getting null
我想在使用路径提供程序包从图库中选取图像后,将图像本地保存在设备上。但 _image 文件变量在 Selecting an Image From Gallery 后变为空。这就是屏幕一直卡在 CircularProgressIndicator Screen 上的原因。你能帮我解决这个 null _image 文件变量吗?
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
class SaveImage extends StatefulWidget {
const SaveImage({ Key? key }) : super(key: key);
@override
_SaveImageState createState() => _SaveImageState();
}
File? _image;
Future<File?> getImage() async{
var image = File(await ImagePicker.platform
.pickImage(source: ImageSource.gallery)
.then((value) => value.path));
final Directory directory = await getApplicationDocumentsDirectory();
final path=directory.toString();
final String fileName = basename(image.path);
// final String fileExtension = extension(image.path);
File newImage = await image.copy('$path/$fileName.jpg');
setState(() {
_image = newImage;
});
}
void setState(Null Function() param0) {
}
class _SaveImageState extends State<SaveImage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Pick Image From'),
SizedBox(height: 30,),
ElevatedButton(onPressed: (){
getImage();
}, child: Text('From Gallery')),
ElevatedButton(onPressed: (){
}, child: Text('From Camera')),
SizedBox(height: 50),
Container(
child: _image!=null?ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.file(
_image!,
fit: BoxFit.cover,
)):Center(child: CircularProgressIndicator(),)
),
],
),
),
),
);
}
}
使用图像类型 PickedFile 类型。例如:
PickedFile _image;
Future pickImageFromGallery(ImageSource source, BuildContext context) async {
var _image = await ImagePicker.platform.pickImage(source: source);
image = _image;
_uploadImage(image, context);
}
**获取图片路径:
imageFile.path
您的代码中有些地方是错误的:
getImage()
函数不在您的 class 中,因此 setState 将不起作用。
您没有检查 ImagePicker.platform.pickImage()
的 return 值,因为它可能为空。在用它初始化文件之前你必须检查它。
directory.toString()
不是 return 目录的路径,而是 return 的“目录:'/something'”。它是用来打印的。如果你想要实际的目录路径,你需要directory.path
如果仍然无法正常工作,请确保按照 image_picker 的要求进行了正确的设置(为 IOS 设置 Info.plist.. .)
这是您的代码,按预期工作:
class SaveImage extends StatefulWidget {
const SaveImage({Key? key}) : super(key: key);
@override
_SaveImageState createState() => _SaveImageState();
}
class _SaveImageState extends State<SaveImage> {
File? _image;
Future<File?> getImage() async {
PickedFile? pickedFile =
await ImagePicker.platform.pickImage(source: ImageSource.gallery);
if (pickedFile == null) {
return null;
}
final File file = File(pickedFile.path);
final Directory directory = await getApplicationDocumentsDirectory();
final path = directory.path;
final String fileName = basename(pickedFile.path);
// final String fileExtension = extension(image.path);
File newImage = await file.copy('$path/$fileName');
setState(() {
_image = newImage;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Pick Image From'),
SizedBox(
height: 30,
),
ElevatedButton(
onPressed: () {
getImage();
},
child: Text('From Gallery')),
ElevatedButton(onPressed: () {}, child: Text('From Camera')),
SizedBox(height: 50),
Container(
child: _image != null
? ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.file(
_image!,
fit: BoxFit.cover,
))
: Center(
child: CircularProgressIndicator(),
)),
],
),
),
),
);
}
}
如果要将图片存入缓存,可以使用flutter_cache_manager库。它允许您在缓存中存储和检索文件。
这是代码,已更新以将文件存储在缓存中。
请注意,我们使用密钥来标识缓存中的文件(我将其设置为文件的路径,但您基本上可以将其设置为任何字符串,只要它对该文件是唯一的即可)。如果您想在整个应用程序范围内使用该文件,您可能需要将密钥存储在可以在那里访问的地方。
class SaveImage extends StatefulWidget {
const SaveImage({Key? key}) : super(key: key);
@override
_SaveImageState createState() => _SaveImageState();
}
class _SaveImageState extends State<SaveImage> {
File? _image;
String? cachedFileKey;
Future<File?> getImage() async {
PickedFile? pickedFile =
await ImagePicker.platform.pickImage(source: ImageSource.gallery);
if (pickedFile == null) {
return null;
}
final File file = File(pickedFile.path);
final Uint8List fileBytes = await file.readAsBytes();
final cachedFile = await DefaultCacheManager()
.putFile(pickedFile.path, fileBytes, key: pickedFile.path);
setState(() {
cachedFileKey = pickedFile.path;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Pick Image From'),
SizedBox(
height: 30,
),
ElevatedButton(
onPressed: () {
getImage();
},
child: Text('From Gallery')),
ElevatedButton(onPressed: () {}, child: Text('From Camera')),
const SizedBox(height: 50),
Container(
child: cachedFileKey != null
?
FutureBuilder<FileInfo?>(future: DefaultCacheManager().getFileFromCache(cachedFileKey!), builder: (context, snapShot) {
if (snapShot.hasData && snapShot.data != null) {
return ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.file(snapShot.data!.file,
fit: BoxFit.cover,
));
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
})
: const Center(
child: CircularProgressIndicator(),
)),
],
),
),
),
);
}
}
我想在使用路径提供程序包从图库中选取图像后,将图像本地保存在设备上。但 _image 文件变量在 Selecting an Image From Gallery 后变为空。这就是屏幕一直卡在 CircularProgressIndicator Screen 上的原因。你能帮我解决这个 null _image 文件变量吗?
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
class SaveImage extends StatefulWidget {
const SaveImage({ Key? key }) : super(key: key);
@override
_SaveImageState createState() => _SaveImageState();
}
File? _image;
Future<File?> getImage() async{
var image = File(await ImagePicker.platform
.pickImage(source: ImageSource.gallery)
.then((value) => value.path));
final Directory directory = await getApplicationDocumentsDirectory();
final path=directory.toString();
final String fileName = basename(image.path);
// final String fileExtension = extension(image.path);
File newImage = await image.copy('$path/$fileName.jpg');
setState(() {
_image = newImage;
});
}
void setState(Null Function() param0) {
}
class _SaveImageState extends State<SaveImage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Pick Image From'),
SizedBox(height: 30,),
ElevatedButton(onPressed: (){
getImage();
}, child: Text('From Gallery')),
ElevatedButton(onPressed: (){
}, child: Text('From Camera')),
SizedBox(height: 50),
Container(
child: _image!=null?ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.file(
_image!,
fit: BoxFit.cover,
)):Center(child: CircularProgressIndicator(),)
),
],
),
),
),
);
}
}
使用图像类型 PickedFile 类型。例如:
PickedFile _image;
Future pickImageFromGallery(ImageSource source, BuildContext context) async {
var _image = await ImagePicker.platform.pickImage(source: source);
image = _image;
_uploadImage(image, context);
}
**获取图片路径:
imageFile.path
您的代码中有些地方是错误的:
getImage()
函数不在您的 class 中,因此 setState 将不起作用。您没有检查
ImagePicker.platform.pickImage()
的 return 值,因为它可能为空。在用它初始化文件之前你必须检查它。directory.toString()
不是 return 目录的路径,而是 return 的“目录:'/something'”。它是用来打印的。如果你想要实际的目录路径,你需要directory.path
如果仍然无法正常工作,请确保按照 image_picker 的要求进行了正确的设置(为 IOS 设置 Info.plist.. .)
这是您的代码,按预期工作:
class SaveImage extends StatefulWidget {
const SaveImage({Key? key}) : super(key: key);
@override
_SaveImageState createState() => _SaveImageState();
}
class _SaveImageState extends State<SaveImage> {
File? _image;
Future<File?> getImage() async {
PickedFile? pickedFile =
await ImagePicker.platform.pickImage(source: ImageSource.gallery);
if (pickedFile == null) {
return null;
}
final File file = File(pickedFile.path);
final Directory directory = await getApplicationDocumentsDirectory();
final path = directory.path;
final String fileName = basename(pickedFile.path);
// final String fileExtension = extension(image.path);
File newImage = await file.copy('$path/$fileName');
setState(() {
_image = newImage;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Pick Image From'),
SizedBox(
height: 30,
),
ElevatedButton(
onPressed: () {
getImage();
},
child: Text('From Gallery')),
ElevatedButton(onPressed: () {}, child: Text('From Camera')),
SizedBox(height: 50),
Container(
child: _image != null
? ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.file(
_image!,
fit: BoxFit.cover,
))
: Center(
child: CircularProgressIndicator(),
)),
],
),
),
),
);
}
}
如果要将图片存入缓存,可以使用flutter_cache_manager库。它允许您在缓存中存储和检索文件。
这是代码,已更新以将文件存储在缓存中。 请注意,我们使用密钥来标识缓存中的文件(我将其设置为文件的路径,但您基本上可以将其设置为任何字符串,只要它对该文件是唯一的即可)。如果您想在整个应用程序范围内使用该文件,您可能需要将密钥存储在可以在那里访问的地方。
class SaveImage extends StatefulWidget {
const SaveImage({Key? key}) : super(key: key);
@override
_SaveImageState createState() => _SaveImageState();
}
class _SaveImageState extends State<SaveImage> {
File? _image;
String? cachedFileKey;
Future<File?> getImage() async {
PickedFile? pickedFile =
await ImagePicker.platform.pickImage(source: ImageSource.gallery);
if (pickedFile == null) {
return null;
}
final File file = File(pickedFile.path);
final Uint8List fileBytes = await file.readAsBytes();
final cachedFile = await DefaultCacheManager()
.putFile(pickedFile.path, fileBytes, key: pickedFile.path);
setState(() {
cachedFileKey = pickedFile.path;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: Column(
children: [
Text('Pick Image From'),
SizedBox(
height: 30,
),
ElevatedButton(
onPressed: () {
getImage();
},
child: Text('From Gallery')),
ElevatedButton(onPressed: () {}, child: Text('From Camera')),
const SizedBox(height: 50),
Container(
child: cachedFileKey != null
?
FutureBuilder<FileInfo?>(future: DefaultCacheManager().getFileFromCache(cachedFileKey!), builder: (context, snapShot) {
if (snapShot.hasData && snapShot.data != null) {
return ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.file(snapShot.data!.file,
fit: BoxFit.cover,
));
} else {
return const Center(
child: CircularProgressIndicator(),
);
}
})
: const Center(
child: CircularProgressIndicator(),
)),
],
),
),
),
);
}
}