flutterstatelesswidgetflutter-alertdialog

How to get context in the any function of StatelessWidget?


We want to show an AlertDialog after some asynchronous processing such as network processes.

When calling 'showAlertDialog ()' from an external class, I want to call it without context. Is there a good way?

class SplashPage extends StatelessWidget implements SplashView {
  BuildContext _context;
  @override
  Widget build(BuildContext context) {
    this._context = context;
    ...
  }

I've considered the above method, but I'm worried about side issues.

Help

My current code

class SplashPage extends StatelessWidget implements SplashView {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: MyStoreColors.eats_white1_ffffff,
      body: Center(
        child: new SvgPicture.asset('assets/ic_splash.svg'),
      ),
    );
  }

  @override
  void showAlertDialog() {

    showDialog<void>(
      context: /*How to get context?*/,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Not in stock'),
          content: const Text('This item is no longer available'),
          actions: <Widget>[
            FlatButton(
              child: Text('Ok'),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  @override
  void moveToHomeContainer() {
  }

  @override
  void moveToLoginContainer() {
  }
}


Solution

  • You should trigger rebuild when the async event complete, either convert your widget to StatefulWidget and call setState() or use a state management solution like Bloc.

    For example using StatefulWidget your code will look like this:

    class SplashPage extends StatefulWidget {
      @override
      State<SplashPage> createState() => _SplashPageState();
    }
    
    class _SplashPageState extends State<SplashPage> implements SplashView {
    
      bool _asynOpDone = false;
    
      /// Call this when the async operation is done.
      void _onAsynOpDone() => setState(() => _asyncOpDone = true);
    
      @override
      Widget build(BuildContext context) {
        if (_asyncOpDone) showAlertDialog(context);
    
        return Scaffold(
          ...,
          ///
        );
      }
    
      @override
      void showAlertDialog(BuildContext context) {
        showDialog<void>(
          context: context,
          builder: ...,
        );
      }
    }