I have a function to upload image to the server. However the widgets starts rebuilding while the image is being uploaded and does not execute code after image is uploaded.
InkWell(
child: Icon(
Icons.camera,
size: 50,
color: Colors.red[400],
),
onTap: () {
_imageFile =
_picker.getImage(source: ImageSource.camera);
_imageFile.then((file) async {
if (file != null) {
fileName = file.path.toString();
var res = await Auth.uploadImage(file);
print("Response for image upload is : ");
print(res);
await setUserData();
}
});
},
)
This is the output on the console from print statements
I/flutter (10171): Calling build Method
I/Timeline(10171): Timeline: Activity_launch_request time:68831133
I/flutter (10171): Uploading image to server
I/flutter (10171): Calling build Method
I/flutter (10171): Image uploaded successfully
As can be seen above no other code is executed and the widget has rebuilt itself. What am I possibly doing wrong?
_imageFile = _picker.getImage(source: ImageSource.camera);
its not right, getImage is an Asynchronous function so you need to wait for it to finish.
do this - _imageFile = await _picker.getImage(source: ImageSource.camera);
If you want to use then do it like this,
_picker.getImage(source: ImageSource.camera).then((image)...your code...)
That's because when you're using _imageFile = _picker.getImage(source: ImageSource.camera); the _imageFile result will come in the future and your next code is executed.
You can fixed the problem either using await:
onTap: () async {
_imageFile =
await _picker.getImage(source: ImageSource.camera);
if (_imageFile != null) {
fileName = file.path.toString();
var res = await Auth.uploadImage(file);
print("Response for image upload is : ");
print(res);
await setUserData();
}
},
Or keep using then with a slight change:
onTap: () {
_picker.getImage(source: ImageSource.camera)
.then((file) async {
if (file != null) {
fileName = file.path.toString();
var res = await Auth.uploadImage(file);
print("Response for image upload is : ");
print(res);
await setUserData();
}
});
},
See explanation about await & then: Async/Await/then in Dart/Flutter
Related
I have an implementation of imagePicker working with the mobile portion of my app, but i am currently trying to make it work on web too. Im getting an image with the following code:
ImagePicker _picker = ImagePicker();
final XFile? _image = await _picker.pickImage(
source: ImageSource.gallery,
imageQuality: 50,
);
if (_image == null) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('No image was selected.')));
}
if (_image != null) {
var f = await _image.readAsBytes();
StorageRepository()
.updateImage(user, _image, index);
}
Which leads to my confusion. My current storage method looks like this:
Future<void> uploadImageWeb(User user, XFile image, int? index) async {
try {
await storage
.ref('${user.id}/${image.name}')
.putFile(
File(image.path),
)
.then(
(p0) => FirestoreRepository().updateUserPictures(
user,
image.name,
index,
),
);
} catch (err) {
print(err);
}
}
Which obviously i cant use xfile, i have to use the Uint8List. But how do i read any data from that in a meaningful way to upload it to the storage bucket?
Thanks!
I trying to get Image from Simulator but it crashes when click as the below GIF:
and this is the code snippet:
Widget buildImage() => GestureDetector(
child: buildAvatar(),
onTap: () async {
final image =
await ImagePicker().getImage(source: ImageSource.gallery);
if (image == null) return;
final directory = await getApplicationDocumentsDirectory();
final id = '_${widget.idUser}_${Uuid().v4()}';
final imageFile = File('${directory.path}/${id}_avatar.png');
final newImage = await File(image.path).copy(imageFile.path);
setState(() => user = user.copy(imagePath: newImage.path));
},
);
and this is the error:
Note that it works fine on real Android device
My app crashes when calling "_submit" function 2 times in a row.
I can pick the picture from gallery and upload it to Firebase Storage but if I call it again the the whole app crashes.
From this button :
floatingActionButton: FloatingActionButton(
onPressed: () => _submit(),
Submit calls a Provider of type Database :
Future<void> _submit() async {
widget.database = Provider.of<Database>(context, listen: false);
await widget.database
.setPicture("regione/citta/comune/lavoro/IDArtista/profilo.png");
return;
}
That calls a function that uploads a picture taken from "imgGallery()" to the database :
Future<void> setPicture(String pathStorage) async {
try {
final File file = await imgFromGallery();
if (file == null) return;
TaskSnapshot task =
await FirebaseStorage.instance.ref(pathStorage).putFile(file);
String image_url = await task.ref.getDownloadURL();
return;
} catch (e) {
print(e);
return;
}
}
imgGallery :
Future<File> imgFromGallery() async {
try {
final ImagePicker _picker = ImagePicker();
final PickedFile imageFile =
await _picker.getImage(source: ImageSource.gallery, imageQuality: 50);
//If there is no image selected, return.
if (imageFile == null) return null;
//File created.
File tmpFile = File(imageFile.path);
//it gives path to a directory - path_provider package.
final appDir = await getApplicationDocumentsDirectory();
//filename - returns last part after the separator - path package.
final fileName = tmpFile.path.split('/').last;
//copy the file to the specified directory and return File instance.
return tmpFile = await tmpFile.copy('${appDir.path}/$fileName');
} catch (e) {
print(e);
return null;
}
}
EDIT : Solved using a real device instead of emulators.
Which device are you experiencing this in? I'm also having this error but only on iOS emulator. It has to do with the Image_Picker package and the FocusNode. Look at this issue on github
I got 2 futures. When I press a GestureDetector I want the first to be completed and then run the second one. But it doesn’t work. What can I do to fix the issue?
Here is my code.
GestureDetector(
onTap: () => pickImage(), uploadImageToFirebase(),
),
Future pickImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_imageFile = File(pickedFile.path);
});
}
Future uploadImageToFirebase(BuildContext context) async {
String fileName = basename(_imageFile.path);
StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child('uploads/$fileName');
StorageUploadTask uploadTask = firebaseStorageRef.putFile(_imageFile);
StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
taskSnapshot.ref.getDownloadURL().then(
(value) => imageUrl = value,
);
}
You can use Future.wait() , It takes a List of Futures and return when all underlying future completes/resolves.
In your code, You can do something like this,
GestureDetector(
onTap: () => pickImageandUploadToFirebase(),
),
The method pickImageandUploadToFirebase() looks like this,
Future<void> pickImageandUploadToFirebase() async {
await Future.wait([
pickImage(),
uploadImageToFirebase(),
]);
}
and you already have the 2 methods pickImage() and uploadImageToFirebase()
Hope this helps, Happy fluttering !
upload this after image pick done,
like this
GestureDetector(
onTap: () => pickImage(context);
),
Future pickImage(context) async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
_imageFile = File(pickedFile.path);
});
uploadImageToFirebase(context);
}
Future uploadImageToFirebase(BuildContext context) async {
String fileName = basename(_imageFile.path);
StorageReference firebaseStorageRef =
FirebaseStorage.instance.ref().child('uploads/$fileName');
StorageUploadTask uploadTask = firebaseStorageRef.putFile(_imageFile);
StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
taskSnapshot.ref.getDownloadURL().then(
(value) => imageUrl = value,
);
}
also, another option is if you need to call one by one in single method.
then return data from first method "pickImage" after retrun done, you call second "uploadImageToFirebase",
I'm new in Flutter and can't get image_picker to open a picture from gallery.
It opens Gallery, but when I tap on a picture, just close gallery
My code is like this.. what i'm missing?
File _imagenTemporal;
var imagen;
Future getImagen(String opcion) async {
if (opcion == "camara") {
imagen = await ImagePicker.pickImage(source: ImageSource.camera);
} else if (opcion == "galeria") {
imagen = await ImagePicker.pickImage(source: ImageSource.gallery);
}
setState(() {
_imagenTemporal = imagen;
}
);
}
ImagePicker is just a FileChooser function that returns a Future<File> widget when the user selects a File from the gallery or takes a picture. You should use the returned file to construct an Image.file widget:
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: showSelectedImage();
),
Future<Image> showSelectedImage() async {
_imagenTemporal = await ImagePicker.pickImage(source: ImageSource.gallery);
return Image.file(_imageTemporal);
}