【发布时间】:2020-01-29 08:38:09
【问题描述】:
我知道 Dart 是单线程的,flutter 也是,所以如果我做一些繁重的任务,它会阻塞 UI 事件队列,但是网络请求需要几秒钟而不阻塞 UI。
那么,为什么 Socket 不会阻塞 UI?困扰我的是为什么socket不会阻塞UI,但是繁重的任务却会,虽然都是异步任务。
例如,这段代码会阻塞 UI
@override
void initState() {
super.initState();
Future((){
var result;
for (var i = 0; i < 1000000; ++i) {
result = 'result is $i';
}
print(result);
});
这段代码是正常的HTTP请求,不会阻塞UI
get() async {
var httpClient = new HttpClient();
var uri = new Uri.http(
'example.com', '/path1/path2', {'param1': '42', 'param2': 'foo'});
var request = await httpClient.getUrl(uri);
var response = await request.close();
var responseBody = await response.transform(UTF8.decoder).join();
}
socket不阻塞UI的原因是把请求过程拆分成多个部分?并将这些部分发送到当前的微任务队列中,正如这个答案所说:
https://stackoverflow.com/a/56783713/6540631
那么,有人知道套接字是如何异步实现的吗? socket是使用Isolate、Future还是其他方式?socket运行在UI线程还是其他线程?
而且,如果我必须执行在 UI 线程中无法拆分的繁重任务(例如文本布局),我该怎么办?
补充说明:
我知道如何使用 Future 和 Isolate,但是我遇到了问题。
如果在隔离中使用 TextPainter.layout 将得到一个本地编译器错误 找不到函数。
我需要排版很多字,而且需要很长时间 (100ms+),它会阻塞 UI 线程。
我该怎么办?
https://github.com/flutter/flutter/issues/30604
UI 包的 Flutter 引擎原生 API 仅可用 在初级隔离中。
https://github.com/flutter/flutter/issues/30604#issuecomment-481380706
现在您必须编写自己的换行逻辑 - 也许作为一个插件。我们目前没有任何用于处理文本的 API 在单独的隔离中布局。 @GaryQian 可能有其他想法 关于这个。
https://github.com/flutter/flutter/issues/30604#issuecomment-526013977
所以我必须在UI线程中进行文本布局(使用TextPainter),虽然写一个插件可以解决这个问题并且效果很好,有没有更简单的方法?
我想我可以从socket的实现细节中得到帮助,所以我提出了这个问题。
【问题讨论】:
-
我既不知道flutter也不知道dart,但我相信文档很好地解释了异步任务的概念:dart.dev/codelabs/async-await#uncompleted
-
1.单线程并不意味着一切都是阻塞的。工作仍然可以异步完成(您可能想阅读coroutines)。 2. Dart 中的每个isolate 都是单线程的,但Dart 支持多个isolate。 3. Flutter 有一个 UI 隔离,但 Flutter engine 使用多个线程来处理各种事情。
-
@Kaenbyou Rin 但是为什么繁重的任务会阻塞UI,网络请求却没有,虽然他们都使用异步任务
-
@jamesdlin 套接字是否使用隔离?困扰我的是为什么socket不会阻塞UI,但是繁重的任务却会,虽然都是异步任务
-
@LuckyDog 套接字是否使用 Isolate 是实现细节。它可能已经启动了一个线程并等待同步 I/O 请求,或者它可能使用了系统本机异步 I/O API(Windows 上的
IOCP或 linux 上的epoll)。