flutter, trying to update a picture from Storage
Here when the image is picked you should directly set it or you can set it after the firebase upload is finished successfully.
But rather than loading an image from Firebase URL after the upload, you can directly load from the picked file as follows;
image = Image.memory(await pickedFile.readAsBytes())
This will instantly set the image and will save you a read call to Firebase. You should always try to minimize the Firebase Reads whenever possible.
Sharki
Updated on December 12, 2022Comments
-
Sharki over 1 year
I'm trying to upload, and update a picture from firebase storage. But for some reason this is not working properly.
This would be the scenario; A user take a picture from his camera, so this picture is uploaded to my storage, so after that I get the
url
picture, so I can use this likeNetworkImage(url)
to update the picture.This is what's happening currently:
Let's say I don't have any picture.
- I update my profile with a new picture. (This works perfectly).
Now let's say I want to update my profile picture, so I take another picture, let's call it
A
so I upload this one.- Nothing happens, picture doesn't change.
But If I try again with a
B
picture, for some reason the picture is updated with theA
picture.
This would be my code and how I'm facing this feature.
I have the next method which is invoked when a user click over his picture. I wait for the result (value) so when I got the result I upload the picture. Then, when the picture is uploaded, I just call to setState and save the
url
into the_imageUrl
variable.After that, I change the "profilePic" attribute from my data base to
true
.String _imageUrl = 'assets/profileDefault.jpg'; bool profilePicture = false; io.File profilePic; Future getFromCamara() async { await ImagePicker().getImage(source: ImageSource.camera).then((value) { profilePic = io.File(value.path); FirebaseStorage.instance.ref().child('picture').putFile(profilePic); }).then((result) { var ref = FirebaseStorage.instance.ref().child('picture'); ref.getDownloadURL().then((loc) => setState(() => _imageUrl = loc)); }); try { FirebaseFirestore.instance .collection('Usuarios') .doc(uid) .update({'profilePic': true}); } catch (e) { print(e.toString()); }
So now, using a StreamBuilder, I get the result of
profilePic
from my DataBase, if is True, I download the URL, and if don't, I just use the Asset default's pic.body: StreamBuilder( stream: FirebaseFirestore.instance.collection('Usuarios').snapshots(), builder: (context, AsyncSnapshot<QuerySnapshot> snapshot1) { if (!snapshot1.hasData) { return Center( child: CircularProgressIndicator(), ); } List<DocumentSnapshot> users = snapshot1.data.docs; for (DocumentSnapshot user in users) { if (user.id == userID) { profilePicture = user['profilePic']; } } if (profilePicture) { FirebaseStorage.instance .ref() .child('picture') .getDownloadURL() .then((loc) => _imageUrl = loc); } else { _imageUrl = 'assets/profileDefault.jpg'; } return Stack( alignment: Alignment.center, children: <Widget>[ Positioned( top: 0, child: Container( color: Color.fromRGBO(255, 0, 0, 70), width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height * .55, ), ), Positioned( top: MediaQuery.of(context).size.height * .015, left: 15, right: 15, child: Container( width: MediaQuery.of(context).size.height * .90, height: 300, padding: EdgeInsets.only(bottom: 10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ GestureDetector( onTap: () => _setPic(context), child: CircleAvatar( radius: 79, backgroundColor: Color(0xFFFFFFFFF), child: CircleAvatar( radius: 75, backgroundImage: profilePicture ? NetworkImage(_imageUrl) : AssetImage(_imageUrl), ), ), ), // More code...
What I'm doing wrong? Why my picture isn't getting updated?
Updated:
I tried this, so I can save in pictureTemp the picture's bytes, calling to setState to rebuild the widget and put the picture with
Image.memory(pictureTemp)
. But it doesn't seem to work.Uint8List pictureTemp; io.File profilePic; Future getFromCamara() async { var pickedFile = await ImagePicker().getImage(source: ImageSource.camera); var image = await pickedFile.readAsBytes(); FirebaseStorage.instance .ref() .child('picture') .putFile(io.File(pickedFile.path)); setState(() { pictureTemp = image; });
child: CircleAvatar( radius: 75, backgroundImage: profilePicture ? pictureTemp == null ? AssetImage(_imageUrl) : Image.memory(pictureTemp) : AssetImage(_imageUrl), ),
-
Sharki over 3 yearsSorry, could you give me an example of how to implement it based on my code? I've updated with what I tried but I'm a little lost. Thanks
-
Sharki over 3 yearsSolved! Instead of using
Image.memory()
method I just used the typeFile
so in the widget I can useFileImage(file)
. Thanks for the hint!