Home > OS >  Do not use BuildContexts across async gaps lint error on presenter layer
Do not use BuildContexts across async gaps lint error on presenter layer

Time:11-04

Stateless Widget

CustomButton.build(
  label: 'login',
  onPressed: () {
    presenter.login(context,username,password);
  },
);

Presenter class (where we have all the logic)

class Presenter {
  Future<void> login(BuildContext context,String username, String password) async {
    showDialog(context);
    var result = await authenticate(username,password);
    int type = await getUserType(result);
    Navigator.pop(context); // to hide progress dialog
    if(type == 1){
        Navigator.pushReplacementNamed(context, 'a');
    }else if(type == 2){
        Navigator.pushReplacementNamed(context, 'b');
    }
  }

  Future<int> getUserType(User user) async {
    //.. some await function
    return type;
  }
}

Now we are getting Do not use BuildContexts across async gaps. lint error on our presenter wile hiding the dialog and screen navigation.

What is the best way to fix this lint.

CodePudding user response:

Don't stock context directly into custom classes, and don't use context after async if you're not sure your widget is mounted yet.

I see the better practice to fix it is to set an onSuccess method as parameter which will have the Navigator.pop(context); from your UI, but call it inside your main method:

  Future<void> login(BuildContext context,String username, String password, void Function() onSuccess) async {
showDialog(context);
var result = await authenticate(username,password);
int type = await getUserType(result);
//Navigator.pop(context); replace this with :
onSuccess.call();
if(type == 1){
    Navigator.pushReplacementNamed(context, 'a');
}else if(type == 2){
    Navigator.pushReplacementNamed(context, 'b');
}}

CodePudding user response:

after an async gap, there is a possibility that your widget is no longer mounted. thats why context is not recommended to use across an async gap. But if you are so sure that your widget is still mounted then, according to flutter team which you can check here, the recommended approach is to store the context before the await keyword. In your case, this is how it should be done:

   Future<void> login(BuildContext context,String username, String password) async {
      final nav = Navigator.of(context);
    showDialog(context);
    var result = await authenticate(username,password);
    int type = await getUserType(result);
    nav.pop(); // to hide progress dialog
    if(type == 1){
       nav.pushReplacementNamed('a');
    }else if(type == 2){
        nav.pushReplacementNamed('b');
     
    }
  }

  • Related