'Flutter: converting an Image object to a base64 string without using a File
I grabbed somewhere the following code to convert a picture to a base64 string without accessing a file :
String ImageToString(Image image) {
String result;
var stream = image.image.resolve(const ImageConfiguration());
stream.addListener(ImageStreamListener((imageInfo, _) async {
var byteData =
await imageInfo.image.toByteData(format: ImageByteFormat.png);
var data = byteData!.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes);
result = base64Encode(data);
}));
// Need to wait for completion here
return result;
}
The problem is that I need to wait for the asynchronous task completion.
- How can I wait for the completion in this case?
- Or else, is there a synchronous wait to perform this?
Solution 1:[1]
I spend two full days of research on this issue and read many sources :
- According to the following long discussion by people developing Dart, Dart's
waitFor
is now deprecated and might well disappear someday. - Moreover,
waitFor
has never been available in Flutter due to some incompatibility because Dart has been adapted deep inside for Flutter's needs. - Its deprecation in Dart means that it won't be introduced in Flutter.
So here is how to deal with this in Dart/Flutter:
- Only an
async
function mayawait
for anotherasync
one. - All
async
functions must return aFuture<...>
(even if aFuture<void>
), thus forcing its caller to beasync
as well, and so on. - The only way to cut these chains of
async
function calls is to reach themain
function or to be able to allow the asynchronous execution of a method at some point (such as a widget's build method for example). - Ther is another way to reduce these
async
chains. For example, say that you need the path of the /tmp directory at some point in your program. This is async
operation. Now, as this path won't change, you may set a global variable at app init time. This is usually directly inmain
, or a function called by it.
Last but not least:
- As for any asynchronous routine, you must take special care passing all the needed information in parameters to keep data integrity, as the execution of
async
functions is delayed, and those data may change in your application before theasync
routine get a chance to be executed. Inbound side effects should thus never be an option here. - Keep in mind in this respect that you should always pass copies of objects to
async
routines!! Indeed, in Dart/Flutter, only the reference of objects are passed by value, not the objects themselves!! This means that modifying an object potentially generates side effects, either inbound or outbound, possibly causing data corruption, for example, when saving data in a file.
I hope it helps.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |