skip to Main Content

I know there are several similar questions listed, but I can not resolve it after I tried some solutions from previous questions. 🙁

I want to do a network check and show a dialog if it has no network connection, so I did the following:

class App extends StatefulWidget {
  const App({super.key});

  @override
  State<App> createState() => _AppState();
}

class _AppState extends State<App> {
  @override
  Widget build(BuildContext context) {
    return MultiBlocProvider(
      providers: [
        BlocProvider(
          lazy: false,
          create: (context) => NetworkBloc()
            ..add(
              const StartMonitor(),
            ),
        ),
      ],
      child: MaterialApp.router(
        routerConfig: router,
        builder: (context, child) {
          return SubWidget(
            child: child,
          );
        },
      ),
    );
  }
}

//try to create a sub-widget
class SubWidget extends StatelessWidget {
  const SubWidget({super.key, this.child});

  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return UpgradeAlert(
      navigatorKey: router.routerDelegate.navigatorKey,
      child: Builder(//try to add build
          builder: (context) {
        return BlocListener<NetworkBloc, NetworkState>(
          listener: (context, state) async {
            if (state is NetworkFailure) {
              await showDialog(
                  context: context,
                  builder: (context) {
                    return const AlertDialog(
                      title: Text('No Network'),
                    );
                  });
            }
          },
          child: child,
        );
      }),
    );
  }
}

the network connection check is fine, but the problem is with showing the dialog. I know there might be some problems with the context, so I tried to create a sub-widget or use a Builder (), but the problem persists.

3

Answers


  1. I just use this package connectivity_plus and it work for me

    Login or Signup to reply.
  2. The context parameter in the listener callback is shadowing the context from the build method. You can change the name of the context parameter in the listener callback to something else, or if you’re not planning to use it change it to _.

    listener: (_, state) async {
    
    Login or Signup to reply.
  3. The parameter builder of MaterialApp works as a wrapper above the inner widgets or inhereted widgets it creates (MediaQuery, Navigator, etc) so in that context those widgets don’t exist yet (they are below). Your widget tree is something like this:

    • SubWidget
      • Navigator
        • Home

    This is from the builder parameter

    {@macro flutter.widgets.widgetsApp.builder}
    
    Material specific features such as [showDialog] and [showMenu], and widgets   
    such as [Tooltip], [PopupMenuButton], also require a [Navigator] to properly function.
    

    What you need is to use your navigator key in your dialog context, and from there use navigatorKey.currentContext;

    class SubWidget extends StatelessWidget {
      const SubWidget({super.key, this.child, required this navigator});
    
      final Widget? child;
    
      @override
      Widget build(BuildContext context) {
        return UpgradeAlert(
          navigatorKey: router.routerDelegate.navigatorKey, /// the context of this key is the one required to make dialogs
          child: Builder(//try to add build
              builder: (context) {
            return BlocListener<NetworkBloc, NetworkState>(
              listener: (context, state) async {
                if (state is NetworkFailure) {
                  await showDialog(
                      context: router.routerDelegate.navigatorKey.currentContext!, /// It may be null but if you initialize it in your route there shouldn't be a problem
                      builder: (context) {
                        return const AlertDialog(
                          title: Text('No Network'),
                        );
                      });
                }
              },
              child: child,
            );
          }),
        );
      }
    }
    

    There is no need to make a Builder wrapper. That’s the reason UpdateDialog from that package asks you to pass the navigator key, to do exactly the same you’re trying and avoid depending on other contexts

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search