首页 > 解决方案 > 如何从小部件调用颤振小部件的状态

问题描述

我是 dart/flutter 的新手,在理解沟通模式时遇到了一些麻烦。

一个反复出现的问题是,我一直希望在一个小部件上公开一个公共方法,以便它可以被其他小部件调用。

问题在于有状态的小部件。在这些情况下,我需要调用小部件状态来完成实际工作。

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

让我举一个具体的例子:

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

当菜单关闭时,它需要遍历它拥有的菜单项列表并告诉每个菜单项隐藏(菜单项不包含在菜单中,因此隐藏菜单不起作用)。

所以菜单有以下代码:

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

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

class MenuItem {
  MenuItemState state;

  close()
  {
    state.close();
  }

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

标签: flutterdartstate

解决方案


我可以通过查看您的更多代码来更好地了解如何解决您的特定问题,但似乎 Flutter 文档在某些方面会为您提供帮助,特别是关于提升状态的部分:

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

为什么?在像 Flutter 这样的声明式框架中,如果你想改变 UI,你必须重新构建它。

…很难通过调用方法从外部强制更改小部件。即使你能完成这项工作,你也会与框架抗争,而不是让它帮助你。

看来您正在尝试与示例中的框架作斗争,并且您担心将公共方法添加到您Widget的 s. 您需要做的是更接近文档中详细说明的内容(其中详细说明了您将在下面看到的所有新类等)。我已经基于此和使用Provider将一个简单的示例放在一起,这使得这种状态管理方法变得容易。这是今年的Google I/O 演讲,鼓励使用它

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您包装在 a Consumer<MenuModel>Now 中的 /s,当Widget重新构建显示菜单的 时,它只是从MenuModel类中获取适当的细节 - 状态的一个真实来源。这将您原本必须处理的代码路径的数量减少到一个,并且在您进行进一步更改时更容易看到正在发生的事情。

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

我建议您阅读有关状态管理的整个页面


推荐阅读