我是飞镖新手,对沟通方式的理解有点麻烦。
一个经常发生的问题是,我一直希望在一个小部件上公开一个公共方法,以便其他小部件可以调用它。
问题在于有状态的小部件。在这种情况下,我需要调低小部件状态以进行实际工作。
问题在于小部件没有状态副本。 我一直在将状态的副本保存在小部件中,但是当然会发出警告,因为它会使小部件易变。
让我举一个具体的例子:
我有一个专门的菜单,可以包含一组菜单项。 每个都是有状态的。
菜单关闭时,需要遍历其拥有的菜单项列表,并告诉每个菜单项隐藏(菜单项在视觉上不包含在菜单中,因此隐藏菜单无效)。
因此菜单具有以下代码:
class Menu{
closeMenu() {
for (var menuItem in menuItems) {
menuItem.close();
}
}
这样可以正常工作,但是当然在MenuItem类中,我需要:
class MenuItem {
MenuItemState state;
close()
{
state.close();
}
但是,当然,由于MenuItem是不可变的,因此将状态对象存储在MenuItem中是一个问题。 (这只是警告,因此代码可以正常工作,但显然不是预期的设计模式。)
答案 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();
},
);
}