Dart future 阻塞主线程

IAm*_*sta 5 future dart flutter

我正在开发一个捕获和处理图像的应用程序。代码的简化版本是:

build() {
   return FloatingActionButton(
        onPressed: processImage,
        child: Icon(
          Icons.camera_alt,
          color: color,
        ),
      ); 
}

processImage(Camera image) async {
   await image.process();   
}
Run Code Online (Sandbox Code Playgroud)

在另一堂课上:

Future<image> process() {
  return Future(() {
    for (int x = 0; x < width; x++) {
      for (int y = 0; y < height; y++) {
        //process image
      }
    }
  });
}
Run Code Online (Sandbox Code Playgroud)

process()运行时,UI 冻结。

为什么会发生这种情况?该函数不是传递给在后台运行的 Future 构造函数吗?

Gre*_*rad 5

由于 Dart 使用事件循环,所有代码(同步和异步)将简单地在相同的代码上运行isolate(以thread其他语言作为类比),只是在不同的时间点运行。因此,当您的process方法出队并执行时,尽管是异步的,但它会阻塞线程并由于执行时间较长而导致帧丢失。该问题的最佳解决方案是在新线程中生成另一个隔离,并在那里执行计算。Flutter 为这种确切的用例提供了一种便捷的方法,称为compute. 它采用一个顶级函数(不在类中,也不是匿名函数),该函数可以有一个基本类型参​​数(包括MapList)作为​​参数,并将在将来的某个时刻返回。有关 的更多信息compute,请参阅上面链接的文档。

如果您有多个需要传递给 的参数compute,则常见模式(除了此用例之外)是创建一个将类的字段序列化为 的方法Map<String, dynamic>,以及一个从 创建对象的工厂构造函数Map<String, dynamic>。如果使用反射,这个过程会更容易,但 Flutter 由于性能原因禁用了它。

compute有关Flutter 文档中的完整示例,请参阅此处: https ://flutter.dev/docs/cookbook/networking/background-parsing