Search code examples
flutterdartnavigator

Flutter pop best practice


I have the following flow Screen 1 -> Screen 2 -> Dialog (in a separate widget).

Screen 2 displays a dialog (Close? Yes or No). If someone presses Yes, I would like to return to the Screen 1, if they press No, just close the dialog and return to Screen 2. What I currently do is when Yes is tapped, I do Navigator.pop(context) twice. Is this a good practice? Is there a way to pass the context of Screen 2 to my dialog widget so I can pop that one directly?


Solution

  • Personally, I think it would be better to pass the response from the dialog back to the page, and let the page handle the rest.

    You can do this:

    //I'm using a raised button just to call the alert as an example... 
    RaisedButton(
        child: Text('Press me'),
        //This part here is the important part
        onPressed: () async {
    
          //You can return anything when you use Navigator.pop
          //In this case I'm returning a bool indicating if the page should close or not.
          //You have to await this because it depends on user input.
          bool shouldPopResult = await showDialog<bool>(
            context: context,
            builder: (context) => AlertDialog(
              //The content of your dialog
    
              actions: <Widget>[
                // The value you pass here in Navigator.of(context).pop
                // is the value that will be stored in shouldPopResult,
                // so if "Yes" is pressed, true will return...
                // and if "No", false is returned.
                FlatButton(
                  child: Text('Yes'),
                  onPressed: () => Navigator.of(context).pop(true),
                ),
                FlatButton(
                  child: Text('No'),
                  onPressed: () => Navigator.of(context).pop(false),
                )
              ],
            ),
          );
    
          // This is for if the user dismisses the dialog without pressing a button
          // In that case shouldPopResult would be null, so I'm setting it to false.
          // You can prevent the user from dismissing the dialog
          // setting barrierDismissible to false in the showDialog method.
          if (shouldPopResult == null) shouldPopResult = false;
    
          // And finally with the dialog already dismissed, you can decide 
          // to go back or not.
          if (shouldPopResult) Navigator.of(context).pop();
        });
    

    As usual you can extract the dialog as a Widget, or extract the function that handles the dialog response altogether or anything else.

    You can see the example of returning data from a page in the flutter documentation here.