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.

73189 次浏览

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

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;
});
},
),
],
),
),
);
}
}

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);
});

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();
},
)
],
);
},
)

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

funcName() {
//Your code
}

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
    });
    }
    });
    

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");

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();
}

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)

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();
}