【问题标题】:Flutter/Dart Async Not Waiting颤振/飞镖异步不等待
【发布时间】:2019-05-07 00:18:27
【问题描述】:

我正在构建我的第一个 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());
} 

Permission Manager 类的 get_permissions() 函数使用 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;
  }
}

当我运行应用程序时,它不会等待函数按预期完成,而是在 Future 更新之前打印“res”的值。

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 在函数中途返回一个值!有谁知道我做错了什么?

【问题讨论】:

    标签: dart async-await flutter future


    【解决方案1】:

    要等待某事,您必须在未来调用 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" 用于调用异步函数的 main() 函数。尽管我的印象是“then”和“await”虽然语法不同(“then”在完成后运行一个函数)但它们的操作方式相同。
    • 不,他们没有。你真的必须使用await
    • 来自 Dart 文档 (dartlang.org/tutorials/language/futures):“要暂停执行直到未来完成,请在异步函数中使用 await(或使用 then())。”但尽管如此,我确实在 main() 函数中使用了 await 无济于事。
    • 一次是不够的。在您的示例中,您需要的不仅仅是一个 await
    • 我认为你不能等待生成的未来。生成的未来对于 then() 运行的回调函数是本地的,并且执行诸如“await SimplePermissions.checkPermission(Permission.ReadExternalStorage).then((result) { ...”之类的操作会产生错误。确实可以返回从回调生成未来,但由于插件不返回布尔值,您需要重写 main() 中的大部分函数
    【解决方案2】:

    搞定了。该问题似乎已使用 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;
      }
    
    }
    

    【讨论】:

    • 这会使get_permissions 上的async 标志无用。
    • 应用程序需要任何功能的读取权限,但简单权限插件异步操作。具体来说,打开应用程序时会读取下载目录中的所有文件。此解决方案会阻止应用程序读取目录,直到授予权限。如果有一种方法可以同步使用插件,那将是理想的,但我认为这是不可能的。
    • 我不是说代码不行,而是语法不对。
    • 参考文档 (pub.dartlang.org/packages/simple_permissions#-readme-tab-)。在没有 async 标志的情况下运行代码并返回非未来 bool 会产生与初始问题中看到的相同的结果(由于插件代码异步运行)。还有其他方法吗?
    猜你喜欢
    • 2021-03-11
    • 2020-09-01
    • 2020-11-28
    • 1970-01-01
    • 2020-11-05
    • 2021-09-05
    • 2020-02-16
    • 2021-03-28
    • 2020-12-25
    相关资源
    最近更新 更多