What I want to achieve: I want to open a pop up explaining my app when it starts.
My approach: As far as I understand it from googling the issue, I should use the showDialog() method. In its most basic form:
showDialog(
context: context,
builder: (context) {
return Text('data');
});
I tried returning actual dialogs (e.g. AlertDialog) but it doesn't change the behavior so I'm just using Text() with a string as a placeholder for now.
The problem:
No matter where I place the showDialog function, it doesn't work as intended (also see scrennshots below):
- Placing it in initState: I get an error message about inherited Widgets being called before the initState is done an explanation about dependiencies I can barely follow.
- Placing it in the build method: I get an error message that setState() or markNeedsBuild() gets called while the app is already buildung widgets.
- Placing it in DidChangeAppLifeCycleState(): This is actually working and opening the pop when I pause the app and then resume it. It is not opening on app startup though.
- Wrapping it in WidgetsBinding.instance!.addPostFrameCallback(): An idea I picked up here:
From build method:
From DidChangeAppLifecycleState (the "succesful" variant:
CodePudding user response:
Will you please try below code in your init method? I hope this may work.
Future.delayed(Duration.zero, () async { myFunction(); });
CodePudding user response:
One of the methods with WidgetsBinding.instance!.addPostFrameCallback() works fine . If you show a normal show dialog with the press of a button too it will produce the same result. Here, you need to wrap the text("data") in a dialog widget such as alertDialog or simpleDialog widget as needed and it will display the dialog within the current scaffold as -
WidgetsBinding.instance!.addPostFrameCallback((_) async { return await showDialog( context: context, builder: (context) { return AlertDialog( content: Text("data"), ); }); });
I tried adding this in the init state and the dialog pops up fine when I restart the app
CodePudding user response:
Using
WidgetsBinding.instance?.addPostFrameCallback
insideinitState
perform its inner task after the 1st frame is complete.addPostFrameCallback
Schedule a callback for the end of this frame.Next issue arise for not having material. You can directly return
AlertDialog
onbuilder
or wrap with any material widget likeMaterial
,Scaffold
..@override void initState() { super.initState(); WidgetsBinding.instance?.addPostFrameCallback((timeStamp) { showDialog( context: context, builder: (context) { return const AlertDialog( content: Text('data'), ); }, ); }); }
CodePudding user response:
Thanks a lot for your answers. I ficed the issue by rewriting with your suggestions; and it works. I tihnk the issue was that I did not have _ or anything else in my WidgetsBinding code. So I did:
WidgetsBinding.instance?.addPostFrameCallback(() {})
instead of
WidgetsBinding.instance?.addPostFrameCallback((_) {})