1

when i try to use CircularProgressIndicator with slow async method, indicator is not shown. When i replace slow custom method with Timer.pereodic() that works fine. I am new in Flutter and do not understand what i am doing wrong

class _MyHomePageState extends State<MyHomePage> {
  bool _inProgress = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          width: 200,
          height: 200,
          child: Column(
            children: [
              _inProgress ? CircularProgressIndicator() : Text("ready"),
              FloatingActionButton(onPressed: _slowMethod)
            ],
          ),
        ),
      ),
    );
  }

  int fibonacci(int n) {
    return n <= 2 ? 1 : fibonacci(n - 2) + fibonacci(n - 1);
  }

  _slowMethod() async {
    setState(() {
      _inProgress = true;
    });

    for (int i = 20; i <= 100; ++i) {
      print(fibonacci(i));
    }

    setState(() {
      _inProgress = false;
    });
  }
}
8
  • why is the method async ? Commented May 3, 2022 at 13:18
  • seems like I found the answer, you used async but there is not await Commented May 3, 2022 at 13:31
  • it does not depend, synchronously it works the same. Actually i want to have "clickable" UI while method executing Commented May 3, 2022 at 13:39
  • okay, you know that when there is await inside the code, execution will pause at that point Commented May 3, 2022 at 13:40
  • 1
    ... note that even with this yielding behaviour you may find the UI sluggish as you are still doing computation on the main Dart thread. Dart Isolates are the way to instantiate additional threads if you actually have heavy computations to perform. (I'm guessing this is just an example.) Commented May 3, 2022 at 14:09

1 Answer 1

1

An async function runs synchronously until the first await keyword.

In the first place, there is no await keyword in the _slowMethod, and that technically means you need to wrap the "what-should-be-asynchronous" operation in a Future and await for it.

So what should be your solution is something like the following for the _slowMethod():

  _slowMethod() async {
    setState(() {
      _inProgress = true;
    });

    await Future(() {
      for (int i = 20; i <= 100; ++i) {
        print(fibonacci(i));
      }
    });

    setState(() {
      _inProgress = false;
    });
  }

But then as Richard Heap (@Richard Heap) pointed in the comments, the above would have issues working. If you run the code, the CircularProgressIndicator will have problems displaying because the main Dart thread has been hijacked by the demanding fibonacci sequence and your UI won't render properly.

I'm supposing that you really might not have a Fibonacci of up to 100 in production code. That probably, you used it to show us the problem. But even if it is the case or you have complex asynchronous operations, you could use Isolates as Richard mentioned.

If the asynchronous operation is not very demanding on the main thread, (like simply doing Future.delayed), awaiting the future should work.

The following snippet will behave as you expect.

  _slowMethod() async {
    setState(() {
      _inProgress = true;
    });

    await Future.delayed(const Duration(seconds: 3));

    setState(() {
      _inProgress = false;
    });
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.