Я создаю свое первое приложение Flutter, и у меня возникла небольшая проблема с асинхронностью.
Когда мое приложение запускается, я хочу, чтобы оно запрашивало разрешения и ждало, пока они не будут предоставлены. Моя функция main () выглядит так:
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());
}
Функция get_permissions () класса Permission Manager использует пакет Flutter Simple 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;
}
}
Когда я запускаю приложение, оно не дожидается завершения функции, как предполагалось, и выводит значение «res» перед обновлением Future.
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
Future возвращает значение в середине функции! Кто-нибудь знает, что я делаю не так?
Чтобы чего-то ждать, вам нужно вызвать ключевое слово await
для будущего вместо .then
.
final result = await future;
// do something
вместо
future.then((result) {
// do something
});
Если вы В самом деле хотите использовать .then
, вы можете дождаться сгенерированного будущего:
await future.then((result) {
// do something
});
Просто убедитесь, что при использовании вложенных асинхронных вызовов ключевое слово async используется для каждого:
await future.then((result) async{
// do something
await future.then((result_2) {
// do something else
});
});
Нет, они этого не делают. Вам действительно нужно использовать await
Из документации Dart (dartlang.org/tutorials/language/futures): «Чтобы приостановить выполнение до тех пор, пока не завершится будущее, используйте await в асинхронной функции (или используйте then ())». Но, несмотря на это, я безрезультатно использовал await в своей функции main ().
Один раз недостаточно. вам нужно больше, чем один await
в вашем примере
Не думаю, что можно ждать сгенерированного будущего. Сгенерированное будущее является локальным для функции обратного вызова, запущенной с помощью then () и выполняющей что-то вроде "await SimplePermissions.checkPermission (Permission.ReadExternalSto rage) .then ((result) {..." генерирует ошибку. Это правда, что вы могли бы вернуть сгенерированное будущее из обратного вызова, но поскольку плагин не возвращает логические значения, вам нужно будет переписать большую часть функции в main ()
Ах ты прав! Мои извинения. Вы действительно можете дождаться результата. К сожалению, в этом случае я возвращаю значения, а он по-прежнему не работает :(. 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
НЕВАЖНО!! Объявление первой функции then () как асинхронной (поскольку вторая является вложенной) выполнило свою работу. Спасибо за вашу помощь, Реми.
Идеально. Я все же рекомендую нет использовать then
. Читать сложнее и ничего не приносит по сравнению со сплющенным async / await
@ RémiRousselet, вы можете мне помочь с этим вопросом. Я тоже столкнулся с аналогичной проблемой. stackoverflow.com/questions/62502334/…
Все заработало. Проблема, похоже, решена с помощью Completer:
import 'package:simple_permissions/simple_permissions.dart';
import 'dart:io' as IO;
import 'dart:async';
class Permission_Manager {
/* Get user permissions */
final Completer c = new Completer();
Future get_permissions() async
{
//Android handler
if (IO.Platform.isAndroid)
{
//Check for read permissions
SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result)
{
//If granted
if (result)
{
c.complete(true);
}
//Otherwise request them
else
{
SimplePermissions.requestPermission(Permission.ReadExternalStorage).then((result)
{
// Determine if they were granted
if (result == PermissionStatus.authorized)
{
c.complete(true);
}
else
{
IO.exit(0); //TODO - display a message
}
});
}
});
}
else
{
c.complete(true);
}
return c.future;
}
}
что делает ваш флаг async
на get_permissions
бесполезным.
Приложению требуются разрешения на чтение для любых функций, но плагин Simple Permissions работает асинхронно. В частности, при открытии приложение читает все файлы в каталоге Downloads. Это решение не позволяет приложению читать каталог до тех пор, пока не будут предоставлены разрешения. Если есть способ использовать плагин синхронно, это было бы идеально, но я не думаю, что это возможно.
Я не говорю, что код не работает, но синтаксис неправильный.
Документы для справки (pub.dartlang.org/packages/simple_permissions#-readme-tab-). Выполнение кода без флага async и возврат логического значения, отличного от Future, дает те же результаты, что и в исходном вопросе (из-за асинхронного выполнения кода плагина). Есть другой способ сделать это?
"await" используется в функции main (), которая вызывает асинхронную функцию. Несмотря на это, у меня создалось впечатление, что «then» и «await», хотя синтаксически различны (с «then», выполняющим функцию после завершения), они работали одинаково.