如何从小部件调用颤动小部件的状态

时间:2019-07-20 14:01:31

标签: flutter dart state

我是飞镖新手,对沟通方式的理解有点麻烦。

一个经常发生的问题是,我一直希望在一个小部件上公开一个公共方法,以便其他小部件可以调用它。

问题在于有状态的小部件。在这种情况下,我需要调低小部件状态以进行实际工作。

问题在于小部件没有状态副本。 我一直在将状态的副本保存在小部件中,但是当然会发出警告,因为它会使小部件易变。

让我举一个具体的例子:

我有一个专门的菜单,可以包含一组菜单项。 每个都是有状态的。

菜单关闭时,需要遍历其拥有的菜单项列表,并告诉每个菜单项隐藏(菜单项在视觉上不包含在菜单中,因此隐藏菜单无效)。

因此菜单具有以下代码:

class Menu{
  closeMenu() {
    for (var menuItem in menuItems) {
      menuItem.close();
    }
  }

这样可以正常工作,但是当然在MenuItem类中,我需要:

class MenuItem {
  MenuItemState state;

  close()
  {
    state.close();
  }

但是,当然,由于MenuItem是不可变的,因此将状态对象存储在MenuItem中是一个问题。 (这只是警告,因此代码可以正常工作,但显然不是预期的设计模式。)

1 个答案:

答案 0 :(得分:0)

我可以看到更多的代码来更好地了解如何解决您的特定问题,但是Flutter文档似乎会在某些方面为您提供帮助,特别是Lifting state up的部分:

  

在Flutter中,将状态保持在使用状态的小部件上方是有意义的。

     

为什么?在Flutter等声明性框架中,如果要更改UI,则必须重新构建它。

     

...很难通过调用外部控件来强制从外部更改该控件。即使可以完成这项工作,您也将在与该框架进行斗争,而不是让它对您有所帮助。

您似乎在尝试在示例中使用该框架,并且对在Widget s中添加公共方法很担心。您需要做的是更接近文档中的详细信息(该文档详细介绍了所有新类,您将在下面看到)。我基于此和Provider的使用将一个简单的示例放在一起,这简化了状态管理方法。这是Google I/O talk from this year encouraging its use

void main() {
  runApp(
    ChangeNotifierProvider(
      builder: (context) => MenuModel(),
      child: MyApp(),
    ),
  );
}


class MyApp extends StatelessWidget {

    …

    // call this when the menu is closed
    void onMyMenuClosed(BuildContext context) {
        var menuModel = getMyMenuModel(context);
        menuModel.hideMenuItems();
    }
}



class MenuModel extends ChangeNotifier {

  bool _displayItems = false;

  void hideMenuItems() {
    _displayItems = false;
    notifyListeners();
  }

  void showMenuItems() {
    _displayItems = true;
    notifyListeners();
  }
}

呼叫hideMenuItems()会呼叫notifyListeners(),此操作便会完成;通知任何侦听器更改,这将提示您重新构建包裹在Widget中的Consumer<MenuModel> / s,现在,当显示菜单的Widget被重建时,它只是抓住了MenuModel类中的适当细节-国家真实的来源之一。这样可以将您原本必须处理的代码路径数量减少到一个,并且使您在进行进一步更改时更容易看到正在发生的事情。

@override
  Widget build(BuildContext context) {
    return Consumer<MenuModel>(
      builder: (context, menuModel, child) {
        return menuModel._displayItems() ? MenuItemsWidget() : Container();
      },
    );
  }

我建议您阅读entire page on state management