Searene
Searene

Reputation: 27544

Need some explanations about use_build_context_synchronously

According to dart's documention, using BuildContext across async invocations is a bad idea. So it suggests we change the following code:

// BAD CODE
void onButtonTapped(BuildContext context) async {
  await Future.delayed(const Duration(seconds: 1));
  Navigator.of(context).pop();
}

to this one:

// GOOD CODE
void onButtonTapped() async {
  await Future.delayed(const Duration(seconds: 1));

  if (!context.mounted) return;
  Navigator.of(context).pop();
}

You can see that the function returns early if the widget is not mounted in the suggested code block. My question is, does it mean that the line Navigator.of(context).pop(); may not get the chance to run? The suggestion changes the code logic, why is it a good idea to write code like this?

Upvotes: 0

Views: 677

Answers (1)

Peter Koltai
Peter Koltai

Reputation: 9744

This rule was introduced by some of the latest upgrades to target avoiding possible errors which could be caused by using an invalid BuildContext.

The build context basically locates the place of a widget in the widget tree. If the widget is removed from the tree, the build context becomes invalid, even if its value is still available in the context variable. In your example, Navigator.of(context).pop() needs a valid context to determine from where and to where should it navigate when invoking the pop method.

If you use only synchronous code in your onButtonTapped function you can be pretty sure that the widget will remain mounted during the execution of the function and therefore you will have a valid build context. (If the user can press your button, the widget is surely mounted.)

This is not true if you use asynchronous code. In this case there can be a considerable delay between onButtonTapped is invoked and execution reaches the line of Navigator.of(context).pop(). And things can happen in your application during this delay which can result in unmounting the widget. For example the user decides to put the application into the background, and you have some logic implemented in the app life cycle state listener that navigates back to home in this case.

So this rule is to make sure that you use build context only if the widget is still in the widget tree, which might not be the case if you run asynchronous code and use build context after awaiting the result of the asynchronous code.

Yes, in this case Navigator.of(context).pop(); might not be called at all. But since the widget is not mounted in this case, it would throw an error and could not perform the navigation anyway.

Upvotes: 3

Related Questions