How to get context in the any function of StatelessWidget?

Issue

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: ...,
    );
  }
}

Answered By – Gan Quan

Answer Checked By – Marilyn (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *