Ant D
Ant D

Reputation: 2683

How to run code after showDialog is dismissed in Flutter?

How to update the Homepage just after the showDialog() is dismissed/disposed? Doesn't seem like it has an onDispose() function.

Found another possible Answer : The WillPopScope can help detect if the back button is pressed.

The widget that will be used in the showDialog, in its build function the widget can be wrapped in return new WillPopScope(child: ______, onWillPop: _______); The code can be run in the onWillPop function. This can update the Homepage below.

Upvotes: 97

Views: 92718

Answers (10)

xaldarof
xaldarof

Reputation: 95

you can use this code below. It will invoke onDismiss and onShow dialog.

   void baseDialog(
        {required Widget content,
        required BuildContext context,
        required Function onDialogShow,
        required Function onDialogDismiss,
        bool barrierDismissible = true}) async {
      onDialogShow.call();
    
      await showDialog(
        context: context,
        barrierDismissible: barrierDismissible,
        builder: (_) {
          return AlertDialog(
            shape: const RoundedRectangleBorder(
              borderRadius: BorderRadius.all(
                Radius.circular(12),
              ),
            ),
            content: Material(color: Colors.white, child: content),
          );
        },
      );
      onDialogDismiss.call();
    }

Upvotes: 1

Huy Nguyen
Huy Nguyen

Reputation: 1109

For me, I used Bloc state management to handle this. The idea is:

//On Dialog
clickOKAction: () => blocCubit.emitOKActionState()
...

//On the bloc file
fun emitOKActionState(){
   emit(OKActionState());
}

//On Widget
listener: (context, state) async {
   if(state is OKActionState) {
        // HANDLE YOUR ACTION HERE
   }
}

Because after showing Dialog, the current widget will be disposed. So you can not use anything related to context for eg, because it's unmounted. This may help solve error like:

This widget has been unmounted, so the State no longer has a context (and should be considered defunct)

Upvotes: 0

Wesley Barnes
Wesley Barnes

Reputation: 671

When tapping outside the dialog the return is null, so I expect a potential null and check for null, which is then false.

onPressed: () async {
bool? result = await showDialog(
  context: context,
  builder: (BuildContext context) {
    return AlertDialog(
      title: Text('Select Entity'),
      content: setupAlertDialogContainer(),
    );
  },
);
if (result ?? false) {
  doWhatYouNeedTo();
}

Upvotes: 5

Jaldip Katre
Jaldip Katre

Reputation: 3406

Simply use await or then. the code in then block will be run after the dialog is dismissed.

showDialog(
  // Your Dialog Code
).then((val){
  Navigator.pop(_context);
});

Upvotes: 217

Manish
Manish

Reputation: 436

If you have made another StatefulWidget for your DialogBox and onDissmissed, you want to call some function in the "dialog calling widget". You can this snippet.

await showDialog(
      context: context,
      builder: (_) => MenuBox(),
);
print("now closed");

Upvotes: 8

CopsOnRoad
CopsOnRoad

Reputation: 267384

There are two approaches.

  1. Use async-await

    bool shouldUpdate = await showDialog<bool>(...);
    if (shouldUpdate) {
      setState(() {
        // we should update the UI
      });
    }
    
  2. Use then

    showDialog<bool>(...).then((shouldUpdate) {
      if (shouldUpdate) {
        setState(() {
          // we should update the UI
        });
      }
    });
    

Upvotes: 1

Smh
Smh

Reputation: 295

Use; .whenComplete(funcName/*not funcName() !*/); after the showDialog()

funcName() {
//Your code
}

Upvotes: 3

Shady Aziza
Shady Aziza

Reputation: 53307

It really depends on the type of updates you want to have.

However, this is a simple example that may help you figure it out.

enter image description here

class Home extends StatefulWidget {
  @override
  _HomeState createState() => new _HomeState();
}

class _HomeState extends State<Home> {
  String _homeData = "initial data";

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(_homeData),
            new RaisedButton(
              child: new Text("Show Dialog"),
              onPressed: ()async{
                bool shouldUpdate = await showDialog(
                  context: this.context,
                  child:new AlertDialog(
                    content: new FlatButton(
                      child: new Text("update home"),
                      onPressed: () => Navigator.pop(context, true),
                    ),
                  ),
                );
                setState(() {
                  shouldUpdate ? this._homeData = "updated" : null;
                });
              },
            ),
          ],
        ),
      ),
    );
  }
}

Upvotes: 29

E.Bradford
E.Bradford

Reputation: 813

Noticed a couple of the above answers were a bit out of date due to the "child" construct used with the AlertDialog object being deprecated now.

Here is what I use now instead for a blocking alert dialog:

          showDialog(
            context: context,
            builder: (BuildContext context) {
              // return object of type Dialog
              return AlertDialog(
                title: new Text("Conversation Request"),
                content:
                    new Text("Have a conversation with this person"),
                actions: <Widget>[
                  // usually buttons at the bottom of the dialog
                  new FlatButton(
                    child: new Text("Accept"),
                    onPressed: () {
                      performAccept();
                    },
                  ),
                  new FlatButton(
                    child: new Text("Ignore"),
                    onPressed: () {
                      performIgnore();
                    },
                  )
                ],
              );
            },
          )

Upvotes: 1

Ekta Bhawsar
Ekta Bhawsar

Reputation: 746

Mobile apps typically reveal their contents via full-screen elements called "screens" or "pages". In Flutter these elements are called routes and they're managed by a Navigator widget. The navigator manages a stack of Route objects and provides methods for managing the stack, like Navigator.push and Navigator.pop.

showDialog(
            context: context,
            child: new AlertDialog(
                title: const Text("Your Title"),
                content: const Text(
                  ...
                   Your Message
                  ...),
                actions: [
                new FlatButton(
                  child: const Text("Ok"),
                  onPressed: () => Navigator.pop(context),
                ),
              ],
            ),
        );

You can check Official Document

Upvotes: 7

Related Questions