kyeonghwan
kyeonghwan

Reputation: 484

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() {
  }
}

Upvotes: 11

Views: 18730

Answers (3)

itmarck
itmarck

Reputation: 61

You can apply Builder pattern concept to simplify this.

There is a little example here.

button_builder.dart

Upvotes: 2

J. Pablo Garc&#237;a
J. Pablo Garc&#237;a

Reputation: 521

To show an AlertDialog you need the context, but in StatelessWidget you do not have access to it directly as in StatefulWidget.

Few options are [1]:

  • passing it as GlobalKey [2]
  • passing build context as parameter to any other function inside StatelessWidget
  • use a service to inject the dialog without context [3]

Cheers.

Upvotes: 7

Gan Quan
Gan Quan

Reputation: 487

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

Upvotes: 3

Related Questions