1

I am trying to show a dialog when a page loads. I have dialogs that get called when a button is tapped I have tried using the same technique but I get different errors.

Here's the beginning part of my code:

class SelectAccount extends StatelessWidget {
  final globalKey = GlobalKey<ScaffoldState>();
  @override
  Widget build(BuildContext context) {
    return ScopedModel(
        model: userModel,
        child: ScopedModelDescendant<UserModel>(builder:
            (BuildContext inContext, Widget inChild, UserModel inModel) {
          return Scaffold(
              key: globalKey,
              extendBodyBehindAppBar: true,
              appBar: AppBar(),
              body: Stack(children: [
                Background(),
                Column(
                  children: [
                    Container(
                      padding: EdgeInsets.only(
                          top: 15 * SizeConfig.heightMultiplier),
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.end,
                        children: [
                          Text(
                            'Please select',
                            style: Theme.of(context).textTheme.headline3,
                          ),
                        ],
                      ),
                      //color: Colors.red,
                    ),
                    Expanded(
                        flex: 2,
                        child: Column(...

Where do I define this function before calling it? Do I need an initState()?

showAlertDialog(BuildContext context) {
  // set up the buttons
  Widget cancelButton = FlatButton(
    child: Text("Cancel"),
    onPressed: () {},
  );
  Widget continueButton = FlatButton(
    child: Text("Continue"),
    onPressed: () {},
  );

  // set up the AlertDialog
  AlertDialog alert = AlertDialog(
    title: Text("AlertDialog"),
    content:
        Text("Information here"),
    actions: [
      cancelButton,
      continueButton,
    ],
  );

  // show the dialog
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return alert;
    },
  );
}

Using it like this:

                                    TextSpan(
                                        text: ' Sign in',
                                        style: TextStyle(
                                          color: buttonColor,
                                          fontSize: 14.0,
                                        ),
                                        recognizer: TapGestureRecognizer()
                                          ..onTap = () {
                                            Navigator.of(context)
                                                .pushReplacementNamed(
                                                    '/signin');
                                          })
                                  ]),
                            ),
                          ],
                        )),
                    Container(
                      padding: EdgeInsets.symmetric(vertical: 70),
                    )
                  ],
                ),
                showAlertDialog(context)
              ]));
        }));
  }
}

showAlertDialog(BuildContext context) {
  // set up the buttons
  Widget cancelButton = FlatButton(
    child: Text("Cancel"),
    onPressed: () {},
  );
  Widget continueButton = FlatButton(
    child: Text("Continue"),
    onPressed: () {},
  );

  // set up the AlertDialog
  AlertDialog alert = AlertDialog(
    title: Text("AlertDialog"),
    content:
        Text("Would you like to continue learning how to use Flutter alerts?"),
    actions: [
      cancelButton,
      continueButton,
    ],
  );

  // show the dialog
  showDialog(
    context: context,
    builder: (BuildContext context) {
      return alert;
    },
  );
}

...throws the following error:

I/flutter ( 4658): RESPONSE []
E/flutter ( 4658): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 2416 pos 18: '!navigator._debugLocked': is not true.
E/flutter ( 4658): #0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:46:39)
E/flutter ( 4658): #1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:36:5)
E/flutter ( 4658): #2      _RouteEntry.handlePush.<anonymous closure> (package:flutter/src/widgets/navigator.dart:2416:18)
E/flutter ( 4658): #3      TickerFuture.whenCompleteOrCancel.thunk (package:flutter/src/scheduler/ticker.dart:399:15)
E/flutter ( 4658): #4      _rootRunUnary (dart:async/zone.dart:1198:47)
E/flutter ( 4658): #5      _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter ( 4658): #6      _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
E/flutter ( 4658): #7      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
E/flutter ( 4658): #8      Future._propagateToListeners (dart:async/future_impl.dart:725:32)
E/flutter ( 4658): #9      Future._completeWithValue (dart:async/future_impl.dart:529:5)
E/flutter ( 4658): #10     Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
E/flutter ( 4658): #11     _rootRun (dart:async/zone.dart:1190:13)
E/flutter ( 4658): #12     _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter ( 4658): #13     _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter ( 4658): #14     _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
E/flutter ( 4658): #15     _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter ( 4658): #16     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter ( 4658):
I/flutter ( 4658): Another exception was thrown: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 3524 pos 12: '!_debugLocked': is not true.
I/flutter ( 4658): Another exception was thrown: 'package:flutter/src/widgets/navigator.dart': Failed assertion: line 3524 pos 12: '!_debugLocked': is not true.

I hope this makes sense

William Chidube
  • 183
  • 3
  • 16
  • Does this answer your question? [Show alert dialog on app main screen load automatically in flutter](https://stackoverflow.com/questions/52164369/show-alert-dialog-on-app-main-screen-load-automatically-in-flutter) – towhid Dec 20 '20 at 16:25

3 Answers3

3

I found this link: How to show alert dialog in flutter without button click

There I learned that in a stateful widget...

  1. You should @override initState() [just as @Mohammed Abdou above suggested]

  2. Call the SchedulerBinding class inside the initState like this:

    @override
     void initState() {
       super.initState();
    
       SchedulerBinding.instance.addPostFrameCallback((_) { 
         _yourFunction();
       });
     }
    
  3. Very !important. You must import the scheduler package:

    import 'package:flutter/scheduler.dart';

  4. Obviously define your _showErrorAlert() function. I did mine outside of everything. Below my entire code.

NOTE: I didn't do any of this inside build.

So basically, my code looks like this:

++++Inside _State class:

  @override
  void initState() {
    super.initState();
    SchedulerBinding.instance.addPostFrameCallback((_) {
    
      _ifLoaded();
    });
  }

  _ifLoaded() async {
    showAlertDialog(context);
  }

I hope this is helpful

William Chidube
  • 183
  • 3
  • 16
2

Convert the page to a stateful widget and override the initState function and then show the dialog there.

Mohamed Abdou
  • 441
  • 3
  • 11
  • Now I get the following error: dependOnInheritedWidgetOfExactType<_LocalizationsScope>() or dependOnInheritedElement() was called before _SelectAccountState.initState() completed... – William Chidube Dec 20 '20 at 16:53
  • @WilliamChidube this is because you are trying to setState within `initState` while rendering is occurring. This causes rendering issues. To over come it, you should wait for initial render to complete, by using `WidgetsBinding.instance.addPostFrameCallback((_) => showMyCustomDialog());` – Mohamed Abdou Dec 21 '20 at 08:38
2

It is not neccessary to use StatefulWidget. In build method write this code:

WidgetsBinding.instance.addPostFrameCallback((_) {
  showDialog(context: context, builder: (_) => alert);
});

This code will be executed once as the widget will be built.

BambinoUA
  • 6,126
  • 5
  • 35
  • 51
  • I get this error: The getter 'instance' isn't defined for the type... – William Chidube Dec 20 '20 at 17:04
  • Hey@BambinoUA Thanks for your answer. I didn't downvote you, I don't know who did. I'll upvote you as your answer was also helpful in leading me towards that path that eventually worked for me. – William Chidube Dec 20 '20 at 18:47