Как получить контекст в любой функции StatelessWidget?

Мы хотим показать AlertDialog после некоторой асинхронной обработки, такой как сетевые процессы.

При вызове showAlertDialog () из внешнего класса я хочу вызвать его без контекста. Есть хороший способ?

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

Я рассмотрел описанный выше метод, но меня беспокоят побочные эффекты.

Помогите

Мой текущий код

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

3 ответа

Решение

Вы должны запустить перестройку, когда событие async завершится, либо преобразуйте свой виджет в StatefulWidget и позвони setState() или используйте решение для управления состоянием, такое как Bloc.

Например, используя StatefulWidget ваш код будет выглядеть так:

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

Чтобы показать AlertDialog, вам нужен контекст, но в StatelessWidget у вас нет прямого доступа к нему, как в StatefulWidget.

Несколько вариантов [1]:

  • передавая его как GlobalKey [2]
  • передача контекста сборки в качестве параметра любой другой функции внутри StatelessWidget
  • использовать службу для ввода диалога без контекста [3]

Ваше здоровье.

Вы можете применить концепцию шаблона Builder, чтобы упростить это.

Здесь есть небольшой пример.

button_builder.dart

Другие вопросы по тегам