Flutter: Refresh image after add - flutter

If I have added data to the flutter in firebase, but I want to add more, the image on the added page still appears before the image, how do I refresh it to return to blank as before?
DateTime now = DateTime.now();
String format = DateFormat('dd:mm:yy').format(now);
var fullImageName = 'foto-$format' + '.jpg';
var fullImageName2 = 'foto-$format' + '.jpg';
final StorageReference ref =
FirebaseStorage.instance.ref().child(fullImageName);
final StorageUploadTask task = ref.putFile(image);
// Wait upload task to complete
final StorageTaskSnapshot downloadUrl =
(await task.onComplete);
// Get image uRL
final String url = (await downloadUrl.ref.getDownloadURL());
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
DocumentReference ref = await db
.collection('resep')
.add({'nama': '$nama', 'resep': '$resep', 'image': '$url', 'email' : widget.email});
setState(() => id = ref.documentID);
Navigator.of(context).pop();
}

Let Say above code you have written is in Page2 which is navigated from Page1.
So when you upload the image on firebase storage and pop the page2. Then you can refresh the page as following,
When you push a new page2 from page1 you can have its pop callback.
// To check if you got your callback or not just pass bool data type with MaterialPageRoute
Navigator.push(context, MaterialPageRoute<bool>(builder: (context) => page2()),).then((bool res) {
// check here if you got your callback data or not
if(res!=null && res==true){
// fetch your updated content here
}
});
When you pop your page2 then,
Navigator.of(context).pop(true);

Related

setState() called after dispose() error after calling async function

I have this button that uploads to Firestore a picture that the user selects and stores the picture url into a varialble to be used to update the user's information.
SELECTION BUTTON calls selectFile().
// SELECTING FILE FOR UPLOAD
Future selectFile() async {
final result = await FilePicker.platform
.pickFiles(allowMultiple: false, type: FileType.image, withData: true);
if (result == null) return;
setState(() {
pickedFile = result.files.first;
texto = Text(pickedFile!.name);
});
}
This successfully changes the state of pickedFiles and Texto variable.
Then I have this other button later in the code that calls uploadFile() and then exits the page with navigator.pop(context).
// UPLOADING FILE AND RETRIEVING DOWNLOAD LINK
Future uploadFile() async {
var fileBytes = pickedFile?.bytes;
var fileName = pickedFile?.name;
var ref = FirebaseStorage.instance.ref().child('UserImages/$fileName');
if (fileBytes == null) {
return '';
}
TaskSnapshot uploadedFile = await ref.putData(fileBytes);
url = await ref.getDownloadURL();
log(url);
if (uploadedFile.state == TaskState.success) {
setState(() { <<<<<<<<--------- setState() called after dispose() ERROR HERE
_petImage = url;
});
}
}
The function does upload the picture to FireStore and even produces a link (tested by using log(url)) but when it reaches the set state it fails.
I have no idea why this is not updating the state of the _petImage variable which stored outside of the main build(context) together with the other variables suck as pickedFile and texto. the setState work fine in other functions but in this function is not working .
what could I be doing wrong here?
It is safe to check if the state is mounted on async and then perform setState.
_() async {
if (mounted) {
setState(() {});
}
}

How to use Uri function properly in Flutter? Difference between Uri and Url

I am confused with the URL and Uri in dart/flutter.
I created this function to be used in my PDF viewer.
static Future<File> loadNetwork(String url) async {
final response = await http.get(Uri.parse(url));
final bytes = response.bodyBytes;
return _storeFile(url, bytes);
}
and I want to call this function to display the specific PDF after clicking a button.
onTap: () async {
setState(() {
isLoading = true;
});
final url = 'http://www.africau.edu/images/default/sample.pdf';
final file = await PDFApi.loadNetwork(url);
openPDF(context, file);
setState(() {
isLoading = false;
});
},
But, still, how do I properly use the Uri and fetch the pdf link. There is an error and I suspect I am using the function wrongly.
It says invalid internet address.
Thanks!
To convert a url to Uri use Uri.parse("url here")

Flutter API Fetch and Sending Data from One screen to another screen

When I am logged in through the API I am getting the value User_id which I am able to print on console, but I want to use it on another screen.
So how can I send the data to another screen?
// First Screen
Future postMethod() async {
var api = Uri.parse("https://demo.likemyfiles.com/DS/api/auth/otp");
Map mapeddate = {
'phone': _phone.text,
'otp': _otp.text,
};
final response = await http.post(api, body: mapeddate);
print(response.body);
var res = json.decode(response.body);
print(res['user_id']);
Navigator.pushNamed(context, StartActivity.id); //here i want to send the User_Id
}
//Second Screen (Start Activity) in this screen there is a function FetchData where i want to use the data
Future fetchdata() async {
var url = await http.get(Uri.parse(
"http://demo.likemyfiles.com/DS/api/api_supervisor/supervisor/3")); //Instead of 3 i want
to use the User_Id variable
}
You should try to declare constructor the first page accept the id and push this id to second page or screen like this below code is first page
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ABC.withId(
id,
),
),
)
the create constructor inside second page screen
class ABC extends StatefulWidget {
#override
_ABCState createState() => _ABCState();
var id;
ABC.withId(String uid) {
id = uid;
}
}
accept your id inside widget using widget.id

Why Flutter "await" doesn't wait?

I'm working on a Flutter app which needs uploading image files to Firebase Storage and then saving urls to Firestore.
Below is my code:
void onSubmit() async {
final fireStore = FirebaseFirestore.instance;
//picList has one element.
List<String> picUrlList = [];
picList.forEach((element) async {
//picUrlList.add(await uploadImage(File(element)));
var url = await uploadImage(File(element));
picUrlList.add(url);
print('1');
});
await fireStore.collection('xxx').doc('yyy').update({
"picUrlList": FieldValue.delete(),
});
await fireStore.collection('xxx').doc('yyy').update({
"picUrlList": FieldValue.arrayUnion(picUrlList),
});
print('2');
print(picUrlList.length);
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => EditPost()),
(Route<dynamic> route) => false,
);
}
Future<String> uploadImage(var imageFile) async {
//var uuid = Uuid().v1();
Reference ref = FirebaseStorage.instance.ref(
user.uid + DateTime.now().millisecondsSinceEpoch.toString() + '.jpg');
await ref.putFile(imageFile);
return await ref.getDownloadURL();
}
I was expecting print('1') to be executed before print('2'). But the printout order is 2, 0, 1.
0 is the length of the list, which I hope can be full of urls just added.
I just don't know what's wrong with the code. Somebody help me.
Thanks.
Your code will be executed normally till the end and then the callbacks from forEach will start executing, so solve this you have two solutions:
Replace forEach by for loop
Use await Future.forEach(picList, (element) async { var url = await uploadImage(File(element));... });

Dart/Flutter: Firebase and Firestore wait for async for loop to complete before continuing

I am trying to submit images to Firebase storage, and then also submit the links to the images to the new record that I am "linking" the images to.
My issue is that if I add image(s) to the data, it seems that the upload makes the rest of the firebase activity not happen (it doesn't make sense to me).
So essentially when I click the FAB then it's supposed to submit the data.
floatingActionButton: FloatingActionButton(
child: Icon(Icons.send),
// SUBMIT THE DATA
onPressed: () async {
setState(() {
// Show the modal spinner until submit is complete
showSpinner = true;
});
// upload images
List<StorageReference> fileRefs = [];
for (var image in imageFiles) {
fileRefs.add(await uploadPic(context, image));
}
// When there are images in the imageFiles array then the below part doesn't run
// but if no images was selected it runs fine, if images are selected they get uploaded
// to firebase storage, but no record gets added. :(
_firestore.collection('InspectionPoints').add({
'project': selectedProject,
// some other fields
'user': loggedInUser.email,
'photoIds': fileRefs.length == 0 ? [] : fileRefs,
'timestamp': DateTime.now(),
//'photoIds' : imageFiles;
});
setState(() {
// <--------------- this still runs
clearForm();
showSpinner = false;
});
} // onPressed
),
I also now tried to put the getting the file refs into an async formula, but it also doesn't work:
// upload images
List<StorageReference> fileRefs = await getFileRefs(context);
And the new function:
Future<List<StorageReference>> getFileRefs(BuildContext context) async {
List<StorageReference> fileRefs = [];
for (var image in imageFiles) {
fileRefs.add(await uploadPic(context, image));
}
return fileRefs;
}
Edit: My Actual uploading code:
Future<StorageReference> uploadPic(BuildContext context, File image) async {
StorageReference firebaseStorageRef = FirebaseStorage.instance.ref().child(basename(image.path));
StorageUploadTask uploadTask = firebaseStorageRef.putFile(image);
StorageTaskSnapshot taskSnapshot = await uploadTask.onComplete;
setState(() {
print('File: ${image.path} uploaded to the cloud');
showInSnackBar('File: ${image.path} uploaded to the cloud');
});
return taskSnapshot.ref;
}
To upload an image to Firebase Storage, you can use the code below.
Future upLoadImage(_providedFile, String folderName, String imageName) async{
//_providedFile -> FILE THAT CONTAINS IMAGE
//folderName -> FOLDER NAME IN FIREBASE STORAGE
//imageName -> NAME OF THE IMAGE THAT WILL BE SAVED ON FIREBASE STORAGE
//FILE UPLOAD LOCATION
//IF YOU DON'T WANT TO ADD IMAGE IN A FOLDER JUST REMOVE
//".child(folderName)" from the line
StorageReference reference = firebasestorage.ref().child(folderName).child('$imageName.jpg');
StorageUploadTask uploadTask = reference.putFile(_providedFile); await
uploadTask.onComplete;
}
I hope this will help you.
You cannot save the type StorageReference to firebase cloud, and due to that type failing to submit the whole submit fails, but because the images are uploaded separately from the data entry, they are already there by the time the data entry fails to submit.
The fix was to convert the StorageReference to string via the .path property.