UI freezes in simple async computation

957

You are blocking your code at await Future.doWhile In fact you would be blocking even if you were not using await This is because dart is single threaded.

When you reach an asynchronous function dart doesn't create a separate thread, it simply goes pass the function, and whenever it is ready it tells the event loop and stands in the back of the line. Very similar to how Nodejs handles things.

You can span an isolate to run expensive operations using compute in dart:async, but I don't know if you can stop the execution of a loop by changing some state. But whatever it is you are tying to do this is probably not the right way.

Good luck

Share:
957
Fernando Santos
Author by

Fernando Santos

Updated on December 26, 2022

Comments

  • Fernando Santos
    Fernando Santos over 1 year

    Context

    I'm working on a function that will execute some actions chronologically and I want to be able to pause its execution and then resume on a button press.

    Problem

    With the code below, the UI gets freezed when the code reaches the await Future.doWhile(() => _isTestPaused);

    Code

    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');
        }
      }
    }
    
  • moneer alhashim
    moneer alhashim over 3 years
    You may be able to control the execution of a loop by using a generator function. So look that up it might help you in this regard.