1

The scenario is that I need to dismiss the dialog of the sign-in page after user is signed in. But after the user is signed in, the authentication branch is no longer available - meaning dialog's parent is nuked (the page that contains several auth options, it is replaced with home page due to user status listeners higher up the widget tree), so attempt to close the dialog programmatically like this fails

      Navigator.of(context, rootNavigator: true).pop();
//or  Navigator.of(context).pop();

The error that I receive reads

Looking up a deactivated widget's ancestor is unsafe [...]

How do I close that kind of floating dialog?

Be Kind
  • 4,712
  • 1
  • 38
  • 45

3 Answers3

1

Perhaps you should use the same context to build the sign-in widget (I mean the parent widget context), if you do so, your sign-in widget will be in the same navigation stack as the rest of the screens, therefore popping it should be safe...

You could take a look at my github repo...

https://github.com/casareafer2908/basic_routes_navigation

Dharman
  • 30,962
  • 25
  • 85
  • 135
Casareafer
  • 145
  • 8
  • Correct me if I'm wrong, as I understand you mean to pass the context of a common ancestor (the one preceding destroyed context) to the child dialog? I was hoping there would be a less intrusive solution, but thanks, upvoted. – Be Kind Sep 24 '21 at 21:30
  • 1
    yeah, you're correct, I think if you pass the context from the parent class (where the build method of the sign-in is) they will share the navigation stack, therefore popping it will just return you to the next available screen in the stack - let me know of your progress as I am curious :D – Casareafer Sep 25 '21 at 03:56
  • thanks, solved by applying `navigatorKey` to the `MaterialApp` and using it to push/close the dialog, as specified in here: https://stackoverflow.com/questions/56280736/alertdialog-without-context-in-flutter – Be Kind Sep 25 '21 at 17:35
1

Solved by using navigatorKey on the root material app:

// Define outside main() function
final navigatorKey = GlobalKey<NavigatorState>();
// Set navigatorKey prop for the MaterialApp
...
return MaterialApp(
              navigatorKey: navigatorKey,
              home: HomePage()
            );
...

then, leverage its context inside the child component to push a new dialog:

final rootContext = navigatorKey.currentContext;

Answer is found in this SO question: AlertDialog without context in Flutter

Be Kind
  • 4,712
  • 1
  • 38
  • 45
0

Demo Widget


class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        ElevatedButton(
          onPressed: () {
            showDialog(
              context: context,
              builder: (dialogCTX) => AlertDialog(
                actions: [
                  ElevatedButton(
                    onPressed: () {
                      Navigator.of(dialogCTX).pop();

                      Navigator.of(dialogCTX).push(MaterialPageRoute(
                        builder: (context) => ChildW(),
                      ));
                    },
                    child: Text("Nav"),
                  ),
                ],
              ),
            );
          },
          child: const Text("opne dialog"),
        )
      ],
    ));
  }
}

class ChildW extends StatelessWidget {
  const ChildW({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Child"),
      ),
      body: ElevatedButton(
        onPressed: () {
          Navigator.of(context, rootNavigator: true).pop();
        },
        child: Text("POP"),
      ),
    );
  }
}


Md. Yeasin Sheikh
  • 54,221
  • 7
  • 29
  • 56