flutter - 如何从小部件调用颤振小部件的状态
问题描述
我是 dart/flutter 的新手,在理解沟通模式时遇到了一些麻烦。
一个反复出现的问题是,我一直希望在一个小部件上公开一个公共方法,以便它可以被其他小部件调用。
问题在于有状态的小部件。在这些情况下,我需要调用小部件状态来完成实际工作。
问题是小部件没有状态的副本。我一直在小部件中保存状态的副本,但是这当然会引发警告,因为它会使小部件可变。
让我举一个具体的例子:
我有一个专门的菜单,可以有一组菜单项。每个都是有状态的。
当菜单关闭时,它需要遍历它拥有的菜单项列表并告诉每个菜单项隐藏(菜单项不包含在菜单中,因此隐藏菜单不起作用)。
所以菜单有以下代码:
class Menu{
closeMenu() {
for (var menuItem in menuItems) {
menuItem.close();
}
}
这样可以正常工作,但当然在 MenuItem 类中我需要:
class MenuItem {
MenuItemState state;
close()
{
state.close();
}
但是当然,将状态对象存储在 MenuItem 中是一个问题,因为 MenuItem 是不可变的。(这只是一个警告,因此代码可以正常工作,但显然不是预期的设计模式)。
解决方案
我可以通过查看您的更多代码来更好地了解如何解决您的特定问题,但似乎 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();
},
);
}
我建议您阅读有关状态管理的整个页面。
推荐阅读
- scala - Spark数据框从一行中选择一列
- multithreading - 即使 TTask 是,TThread 也无法识别。(System.Threading 在使用接口部分)
- javascript - 如何在html中创建指向单点的蜘蛛图
- python - FailedPreconditionError(参见上面的回溯):GetNext() 失败,因为迭代器尚未初始化
- android - TextView SetText 不刷新 UI Android 上的文本
- android - (Android) 从 BLE 设备的自定义特征中获取数据的问题
- mysql - 我如何计算表中的项目数并与mysql数据库中不同表中的类别连接
- c++ - 如何在 C++ 中输入鼠标按钮
- typescript - Typescript 泛型类型不强制类型安全
- android - 在 kotlin 中实现状态持久化