ScaffoldMessenger.of(контекст).showSnackBar() не работает при вызове непосредственно внутри функции сборки виджета

#flutter #dart #toast #snackbar

Вопрос:

В поисках примеров использования flutter SnackBar с ScaffoldMessenger , я нашел только использование с onPressed функцией:

     Widget build(BuildContext context) {
        return Container(
            child: ElevatedButton(
              child: ...,
              onPressed: () => _showToast(context),
            ));
      }
    
      void _showToast(BuildContext context) {
        final scaffold = ScaffoldMessenger.of(context);
        scaffold.showSnackBar(
          SnackBar(content: const Text('Added to favorite')),
        );
      }
    }
 

но ни один из примеров не объясняет, почему его нужно использовать только с onPressed,
поэтому я попробовал его сам и использовал непосредственно внутри функции сборки:

          Widget build(BuildContext context) {
           _showToast(context);   <---
           return Container(
              child: ElevatedButton(
                ...,
            ));
      }
 

но чем я получил эту ошибку:

введите описание изображения здесь

и я не уверен, почему это происходит.

В итоге я дал Эшафоту ключ и использовал этот GlobalKey<ScaffoldState> подход, но я действительно хочу понять, почему использование ScaffoldMessenger.of(context).showSnackBar() без обратного вызоваonPressed не сработало

Ответ №1:

в то время ScaffoldMessenger.of(context) как нам нужно дать некоторое время для правильной визуализации(для полного эшафота). мы можем узнать время по addPostFrameCallback . Также, если вы попытаетесь показать середину виджетов, 1-я часть будет отображаться, но остальные виджеты столкнутся с этой проблемой.

вот суть build метода.

   WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
      _showToast(context);
    });

 

чтобы правильно понять концепцию, мы можем сделать что-то вроде этого.

 Scaffold(
      body: Container(
        height: 100,
        color: Colors.cyanAccent,
        child: Column(
          children: [
            Text("This text will render "),
            Builder(builder: (context) {
              _showToast(context);

              ///but you will be able to see Message
              return Text("it will cause error");
            }),
            Text("This text will not render "),
          ],
        ),
      ),
    );
 

Комментарии:

1. Я принял этот ответ, поскольку он объясняет концепцию полного рендеринга лесов и дает пример для этой концепции.

Ответ №2:

Попробуйте добавить или объявить свою закусочную в будущем.делейд

 Future.delayed(Duration.zero, () async {
                  yourSnackBarFunction();
                });
 

Комментарии:

1. Моя цель-понять причину, по которой я получаю ошибку. хотя я предполагаю, что ваше решение сработает…

2. Я не рекомендую этого делать, это как-то «обманывает» рамки и вообще не рекомендуется.

3. Я вроде как решил проблему с GlobalKey (как я уже упоминал в посте), но я действительно хочу понять, почему это происходит

4. Подумайте о методе «сборки» как о рецепте для движка Flutter, как собрать свой виджет, если произойдет что-то, что приведет к необходимости перестройки. Видишь api.flutter.dev/flutter/material/ScaffoldState/build.html .

5. @vigdora Я думаю о будущем. удалено, которое выполняет свои вычисления с задержкой. [Вычисление] будет выполнено по истечении заданного [времени], и будущее завершится результатом вычисления.

Ответ №3:

В Flutter функция сборки вызывается самой платформой всякий раз, когда требуется перестроить виджет. Это может произойти много раз!

С другой стороны, вы обычно хотите отобразить тост / закусочную, когда хотите о чем-то сообщить своему пользователю. Таким образом, вы можете отображать закусочную из onPressed и многих других мест, но сама функция сборки предназначена только для создания виджета и не отвечает напрямую на действия пользователя.

Комментарии:

1. Спасибо, но когда flutter связывает вас с использованием контекста с помощью scaffoldMessenger, он ограничивает использование его только методом сборки в виджетах без состояния… и я, возможно, захочу использовать тосты вне функции сборки..

2. Возможно, я ошибаюсь, но я думаю, что вы можете получить доступ к контексту и из других мест, а не только из метода сборки. Например, если вы объявляете метод в «class _SomeState расширяет состояние<Некоторые>», у вас есть контекст в методе. Попробуйте и извините, если я ввожу вас в заблуждение, но я помню, как использовал это.

3. api.flutter.dev/flutter/widgets/State/context.html

4. Проверьте ссылку выше, мне кажется, что есть средство получения с именем «контекст», к которому вы можете получить доступ из объектов состояния. Немного сбивает с толку то, что функции сборки получают это как параметр функции с тем же именем.

5. Я проверю вышесказанное, но я думаю, что ваша идея связана с виджетами с отслеживанием состояния, и мой вопрос больше касается состояния без состояния, я начинаю чувствовать, что ключевой подход (GlobalKey<ScaffoldState>) является правильным, поскольку он позволит мне более гибко