FLUTTER: Двойное пересоздание виджет StateFull -> Build

Как (можно ли) устранить двойное создание виджета Widget build(BuildContext context)?

Классическая структура есть класс от StatefullWidget

class BodyView extends StatefulWidget {
  @override
  _BodyViewState createState() => _BodyViewState();
}

И есть тело в котором переопределен initState (Добавленна загрузка _loadSelect() из SharedPreferences значения selectPage с setState()-ом)

class _BodyViewState extends State<BodyView> {
  int selectedPage;

  @override
  void initState() {
    super.initState();
    _loadSelect();
  }
  
  @override
  Widget build(BuildContext context) {

Получается что Widget создается до выполнения метода initState(и пытается вывести себя на экран, при этом значение selectedPage не определено). После чего выполняется initState и еще раз запускает пересоздание Widget-а.

Пробовал через Future сделать - аналогичная ситуация. Что я не правильно делаю? Или как правильно. Или это проблема Flutter-а и её не исправить?


Ответы (1 шт):

Автор решения: MiT

Или это проблема Flutter-а и её не исправить?

В первую очередь это не понимание как работает Flutter. Для начала я рекомендую прочитать про разницу между StatlessWidget и StatefulWidget, а также как работает асинхронность в Flutter.


Ответ на ваш изначальный вопрос:

В initState вы запускаете асинхронную функцию (то есть не блокируете дальнейшие построение widget, что является правильным), далее widget строиться, но без значения selectedPage (что скорее всего и дает ошибку). После чего _loadSelect завершает свою работу и вызывает setState, тем самым вызывая перестроение widget уже во второй раз.

Чтобы не перестраивать весь widget можно использовать FutureBuilder, он будет сам следить и вызывать перестроение внутри себя когда асинхронная операция будет завершаться. Но это не освобождает вас от того, что на момент когда асинхронная операция выполняется вам нужно что-то показать пользователю (лоадер и т.д.).

Либо использовать State Management: Redux, BLoC, MobX...


Widget никогда не создается до выполнения метода initState

→ Ссылка