Flutter / Dart - Как я могу изменить состояние StatefulWidget из другого StatefulWidget в другом файле?

Фон: у меня есть StatefulWidget для панели навигации, которая отображает значок текущей страницы как активный. Он уже обновляется правильно, если пользователь нажимает разные значки на панели навигации. Но мне также нужно, чтобы он обновлял активный значок, если пользователь нажимает кнопку за пределами навигационной панели, код которой находится в другом StatefulWidget. Для этого я представил, что функция кнопки должна вызывать функцию из StatefulWidget на панели навигации, которая использует setState и индекс, переданный в качестве параметра для обновления активного значка. Однако мои попытки пока не увенчались успехом. Произошла следующая ошибка:

Следующее утверждение было выдано при обработке жеста:
I / flutter (24216): setState () вызвано в конструкторе: TabsState # 1bf6b (состояние жизненного цикла: создано, нет виджета, не смонтировано) I / flutter (24216): Это происходит, когда вы вызываете setState () для объекта State для виджета, который еще не был вставлен в I / flutter (24216): дерево виджетов. Нет необходимости вызывать setState () в конструкторе, поскольку состояние
I / flutter (24216): уже предполагается грязным при его первоначальном создании. `}

Код родительского виджета был:

[...]
  Tabs({Key key, this.menuScreenContext, this.initialIndex}) : super(key: key);

  final int initialIndex;

  @override
  TabsState createState() => TabsState();
}

class TabsState extends State<Tabs> {
  PersistentTabController controller;

  @override
  void initState() {
    super.initState();
    controller = PersistentTabController(initialIndex: widget.initialIndex);
  }

  List<Widget> _buildScreens() {
    return [
      HomeScreen(),
[...]
void updateIndex(int index) {
    setState(() {
      controller.index = index;
    });
  }
}

Код из дочернего виджета (класс _HomeScreenState расширяет State):

[...]  
    CustomButton(
            function: () {
              final tabsState = TabsState();
              tabsState.updateIndex(2);
[...]

Я попытался решить эту проблему, вызвав initState () в дочернем виджете перед вызовом setState (), но это не сработало, и, насколько я понимаю, он создает другой объект состояния, связанный с виджетом с отслеживанием состояния, что кажется неправильным подходом в в этом случае, поскольку я хочу изменить только состояние существующего объекта навигационной панели.
Мой вопрос: как я могу вызвать эту функцию updateIndex (int index), которая использует setState для обновления активного значка навигационной панели, из функции Button внутри другого StatefulWidget, расположенного в другом файле, успешно?


person Giovana Meloni Craveiro    schedule 06.04.2021    source источник


Ответы (1)


Я сделал это! На основании ответов на этот вопрос (Контроль состояния извне StatefulWidget), Я понял, что способ получить доступ к состоянию другого виджета с отслеживанием состояния заключается в следующем:

1- ›Объявите класс State, который вы хотите изменить, в виджете с отслеживанием состояния дочернего виджета, используя findAncestorStateOfType, который находит предка этого типа. Например:

class HomeScreen extends StatefulWidget { 
  static TabsState of(BuildContext context) =>context.findAncestorStateOfType<TabsState>(); 

2- ›вызовите функцию из любого места внутри класса состояния этого виджета с отслеживанием состояния, ссылаясь на класс виджета с отслеживанием состояния и используя (context). Например:

function: () {
          HomeScreen.of(context).updateIndexFromCart(2);

3- ›Эта функция должна находиться внутри класса состояния виджета с отслеживанием состояния, на который вы ранее ссылались, и тогда можно будет использовать setState как обычно. Например:

void updateIndexFromCart(int index) {
setState(() {
  controller.index = index;
  cartScreenFlag = true;
});

}

person Giovana Meloni Craveiro    schedule 16.04.2021