【问题标题】:UI freezes in simple async computationUI 在简单的异步计算中冻结
【发布时间】:2021-03-27 08:03:30
【问题描述】:

上下文

我正在开发一个按时间顺序执行某些操作的函数,我希望能够暂停其执行,然后在按下按钮时恢复。

问题

使用下面的代码,当代码到达await Future.doWhile(() => _isTestPaused); 时,UI 会冻结

代码

import 'package:flutter/material.dart';

class Sample extends StatefulWidget {
  const Sample();

  @override
  _SampleState createState() => _SampleState();
}

class _SampleState extends State<Sample> {
  String _text;
  bool _isTestPaused;

  @override
  void initState() {
    _text = '';
    _isTestPaused = false;
    WidgetsBinding.instance.addPostFrameCallback((_) => _run());
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Expanded(child: Text(_text)),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => _isTestPaused = !_isTestPaused),
        child: Icon(_isTestPaused ? Icons.play_arrow : Icons.pause),
      ),
    );
  }

  Future<void> _run() async {
    int count = 0;

    for (int i = 0; i < 100; i++) {
      await Future.delayed(const Duration(seconds: 1));
      await Future.doWhile(() => _isTestPaused);
      setState(() => _text += '${count += 1}\n');
    }
  }
}

【问题讨论】:

    标签: android flutter user-interface dart async-await


    【解决方案1】:

    使用 Future 方法运行异步代码。然后使用 Future Builder 调用。由于 Flutter 是单线程的,直接从内部调用 async 会导致应用冻结。

    【讨论】:

      【解决方案2】:

      你在await Future.doWhile 阻塞了你的代码事实上,即使你没有使用await 你也会阻塞,这是因为 dart 是单线程的。

      当你到达一个异步函数时,dart 不会创建一个单独的线程,它只是简单地传递函数,并且只要它准备好,它就会告诉事件循环并站在行的后面。非常类似于 Nodejs 的处理方式。

      您可以使用compute 中的dart:async 跨越隔离来运行昂贵的操作,但我不知道您是否可以通过更改某些状态来停止循环的执行。但无论你想做什么,这可能都不是正确的方法。

      祝你好运

      【讨论】:

      • 您可以使用生成器函数来控制循环的执行。因此,请查看它可能会在这方面对您有所帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-12
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      • 2015-06-07
      • 2014-08-08
      • 2015-02-01
      相关资源
      最近更新 更多