Home > database >  Need some explanations about use_build_context_synchronously
Need some explanations about use_build_context_synchronously

Time:10-06

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?

CodePudding user response:

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 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 pop method.

If you use only synchronous code in your onButtonTapped function you can be pretty sure the 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, it is sure that the widget is mounted.)

This is not true if you use asynchronous code. In this case there can be a considerable delay between onButtonTapped is invoked and it reaches the line of Navigator.of(context).pop(). And things can happen in your application during this delay which can result in dismounting 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.

  • Related