【问题标题】:Why Future block the ui but network requests don't in flutter为什么未来会阻止用户界面但网络请求不会颤动
【发布时间】:2019-11-09 00:35:38
【问题描述】:

我知道 Future 将在事件队列中运行。但是事件队列也在主隔离上运行,如果我将来执行一些繁重的任务(例如,计算从 1 到 1000000 的总和),它将阻塞我的 ui 代码。 但是Future在网络操作中不会阻塞ui(比如await httpClient.getUrl(uri))。 为什么使用 future 的网络请求需要几秒钟而不阻塞 UI,而计算操作会阻塞 UI?

@override
void initState() {
super.initState();
Future((){
  var result;
  for (var i = 0; i < 1000000; ++i) {
    result = 'result is $i';
  }
  print(result);
});

}

如果我在 initState() 中使用 Future 执行一些繁重的任务,UI 将被阻塞。

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    Dart 中的隔离是单线程的。隔离者一次只能做一件事。

    异步函数基本上是cooperative multitasking 的一种形式。一个函数必须yield(通常通过await)以允许其他操作在隔离中执行。

    您的计算没有产生,因此它必须在 UI 恢复处理事件之前完整运行,并且 UI 将无响应。如果你改变了它:

    Future(() async {
      var result;
      for (var i = 0; i < 1000000; ++i) {
        result = 'result is $i';
        await Future.delayed(Duration.zero);
      }
      print(result);
    });
    

    那么您应该会发现 UI 可以定期处理事件并且应该具有保持响应的外观。 (请注意,由于额外的开销,您的计算将需要更长的时间才能完成。)

    【讨论】:

    • @Turisla Huh。我想我应该先尝试一下。我怀疑使用await null 不起作用,因为虽然它延迟执行,但每次迭代都会添加到当前microtask queue,在返回事件循环之前同步处理。我已经更新了我的答案。
    【解决方案2】:

    让我简单回答一下,网络请求(dart:io 中的 HttpClient)实际上是在另一个隔离中结束的。

    在 socket_patch.dart 文件中找到_NativeSocket 部分,继续向下搜索,您将看到this statement (the link is likely to point to the wrong line as the SDK is constantly updated in the future)

    _EventHandler._sendData(this, eventPort!.sendPort, fullData);
    

    是不是很眼熟?

    【讨论】:

      猜你喜欢
      • 2020-01-29
      • 1970-01-01
      • 2016-05-08
      • 1970-01-01
      • 1970-01-01
      • 2015-08-20
      • 2013-11-19
      • 1970-01-01
      • 2012-05-17
      相关资源
      最近更新 更多