Flutter/Dart Async Not Waiting
To await something you have to call the await
keyword on a future instead of .then
final result = await future;
// do something
instead of
future.then((result) {
// do something
});
If you really want to use .then
then you can await the generated future:
await future.then((result) {
// do something
});
Just ensure that when using nested asynchronous calls that the async keyword is used on each:
await future.then((result) async{
// do something
await future.then((result_2) {
// do something else
});
});
![Topazoo](https://lh4.googleusercontent.com/-zzvmc_P3guo/AAAAAAAAAAI/AAAAAAAAAAA/AGDgw-h1sG9RK_944TvRwtndqOEABOHP3g/mo/photo.jpg?sz=256)
Topazoo
Updated on July 18, 2022Comments
-
Topazoo almost 2 years
I'm building my first Flutter application and I've run into a bit of an async issue.
When my application executes I'd like it to ask for permissions and wait until they are granted. My main() function looks like this:
import 'permission_manager.dart' as Perm_Manager; void main() async { //Ensure valid permissions Perm_Manager.Permission_Manager pm = Perm_Manager.Permission_Manager(); var res = await pm.get_permissions(); print(res); return runApp(MyApp()); }
The Permission Manager class' get_permissions() function uses the Flutter Simple Permissions package to check and ask for permissions.
import 'package:simple_permissions/simple_permissions.dart'; import 'dart:io' as IO; import 'dart:async'; class Permission_Manager { /* Get user permissions */ Future<bool> get_permissions() async { //Android handler if (IO.Platform.isAndroid) { //Check for read permissions SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result) { //If granted if (result) return true; //Otherwise request them else { SimplePermissions.requestPermission(Permission.ReadExternalStorage) .then((result) { // Determine if they were granted if (result == PermissionStatus.authorized) return true; else IO.exit(0); //TODO - display a message }); } }); } else return true; } }
When I run the application it does not wait for the function to complete as intended and prints the value of "res" before the Future is updated.
Launching lib\main.dart on Android SDK built for x86 in debug mode... Built build\app\outputs\apk\debug\app-debug.apk. I/SimplePermission(15066): Checking permission : android.permission.READ_EXTERNAL_STORAGE I/flutter (15066): null I/SimplePermission(15066): Requesting permission : android.permission.READ_EXTERNAL_STORAGE
The Future returns a value midway through the function! Does anyone know what I'm doing wrong?
-
Topazoo over 5 years"await" is used in the main() function which calls the asynchronous function. Notwithstanding I was under the impression that "then" and "await" while syntactically different (with "then" running a function after completion) they operated the same way.
-
Rémi Rousselet over 5 yearsNo they don't. You really have to use
await
-
Topazoo over 5 yearsFrom the Dart documentation (dartlang.org/tutorials/language/futures): "To suspend execution until a future completes, use await in an async function (or use then())." But despite this I did use await in my main() function to no avail.
-
Rémi Rousselet over 5 yearsthat makes your
async
flag onget_permissions
useless. -
Rémi Rousselet over 5 yearsOnce is not enough. you need more then just one
await
in your example -
Topazoo over 5 yearsThe application requires read permissions for any functionality but the Simple Permissions plugin operates asynchronously. Specifically, when opening the application reads all files in the Downloads directory. This solution stops the application from reading the directory until permissions are granted. If there's a way to use the plugin synchronously that would be ideal, but I don't think it's possible.
-
Rémi Rousselet over 5 yearsI'm not saying the code doesn't work, but that the syntax is not the right one.
-
Topazoo over 5 yearsThe docs for reference (pub.dartlang.org/packages/simple_permissions#-readme-tab-). Running the code without the async flag and returning a non-Future bool produces the same results as seen in the initial question (due to the plugin code running asynchronously). Is there another way to do it?
-
Topazoo over 5 yearsI don't think you can await the generated future. The generated future is local to the callback function run by then() and doing something like "await SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result) { ..." generates an error. It's true that you could return the generated future from the callback, but since the plugin doesn't return boolean values you'd need to rewrite most of the function in main()
-
Topazoo over 5 yearsAh you are correct! My apologies. You can indeed await the result of then. Unfortunately in this case I am returning values and it still doesn't work :(.
I/SimplePermission(18817): Checking permission : android.permission.READ_EXTERNAL_STORAGE I/flutter (18817): Instance of 'Future<bool>' I/SimplePermission(18817): Requesting permission : android.permission.READ_EXTERNAL_STORAGE
-
Topazoo over 5 yearsNEVERMIND!! Declaring the first then() function as asynchronous (since the second is nested) did the job. Thanks for all your help Rémi.
-
Rémi Rousselet over 5 yearsPerfect. I'd still recommend you to not use
then
though. It's harder to read and doesn't bring anything compared to the flattened async/await -
Roxx about 4 years@RémiRousselet can you help me with this question. I am also facing similar issue. stackoverflow.com/questions/62502334/…