gpt4 book ai didi

flutter - 更新通知程序值后未调用 ValueListenableBuilder 构建器方法

转载 作者:行者123 更新时间:2023-12-05 05:39:46 28 4
gpt4 key购买 nike

我正在尝试从父小部件更新通知程序值,而 ValueListenableBuilder 是在子小部件中定义的,但构建器在更改值后未调用。

这是父部件代码,其中我将两个子部件声明为 StatefulWidget 并且还声明了一个 Notifier 类的静态对象。我正在从 secondChild() 小部件调用方法 updateMenuItemList 像这样 HotKeysWidget.of(context)!.updateMenuItemList(currentCat!['items']); 更新 firstChild() 小部件的列表:

class HotKeysWidget extends StatefulWidget {
static HotKeysWidgetState? of(BuildContext context) =>
context.findAncestorStateOfType<HotKeysWidgetState>();

@override
State<StatefulWidget> createState() {
// TODO: implement createState
return HotKeysWidgetState();
}
}

class HotKeysWidgetState extends State<HotKeysWidget> {
static DealsNotifier appValueNotifier = DealsNotifier();

updateMenuItemList(List<Food> list) {
appValueNotifier.updateMenuList(list);
}

@override
Widget build(BuildContext context) {
return Container(child: Column(children: [
firstChild(),
secondChild(),
],
),
);

}

}

这是我的通知程序类:

class DealsNotifier {
ValueNotifier<List<Food>> dealList = ValueNotifier([]);
ValueNotifier<List<Food>> menuitemList = ValueNotifier([]);
ValueNotifier<List<Map<String,dynamic>>> categoryList = ValueNotifier([]);

void updateDealsList(List<Food> list) {
dealList.value = list;
print('DEAL LIST IN CLASS: ${dealList}');
}

void updateMenuList(List<Food> list) {
menuitemList.value = list;
print('PRICE CHANGE: ${menuitemList.value[2].price}');
print('MENU ITEM LIST IN CLASS: ${menuitemList}');
}

void updateCategoryList(List<Map<String,dynamic>> catList) {
categoryList.value = catList;
print('DEAL LIST IN CLASS: ${categoryList}');
}
List<Food> getDealList() {
return dealList.value;
}

List<Food> getMenuitemList() {
return menuitemList.value;
}

List<Map<String,dynamic>> getCategoryList() {
return categoryList.value;
}
}

这是父代码中名为firstChild() 的子控件。这里声明了 ValueListenerBuilder:

class firstChild extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return firstChildState();
}

}

class firstChildState extends State<firstChild> {

@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: HotKeysWidgetState.appValueNotifier.menuitemList,
builder: (context, List<Food> value, widget)
{
print('MENUITEM LIST UPDATED: ${value}');
return HotkeysMenuItemsWidget(
key: menuItemsKey,
currentMenu:currentCat != null ? value : [],
);
},
);

}
}

class secondChild extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return secondChildState();
}

}

class secondChildState extends State<secondChild> {

@override
Widget build(BuildContext context) {
return RaisedButton(

onPressed: (){
HotKeysWidget.of(context)!.updateMenuItemList([]);
},
child: Text(
'UPDATE',
maxLines: 2,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 12,
),
),
);

}
}

谁能帮我解决这个问题。

提前致谢

最佳答案

虽然共享的代码仍然不足以完全重现您的情况,但我可以提供一些建议。

StatefulWidgetsstate 部分默认是私有(private)的,这是有原因的。您不应该公开它们只是为了访问内部的变量,还有其他几个变量可以访问小部件内的外部类。

所以任何时候你做这样的事情

class firstChild extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return firstChildState();
}
}

class firstChildState extends State<firstChild> {
@override
...

只要坚持 StatefulWidget 的默认语法,类也应该在 UpperCamelCase 中首字母大写。

class FirstChild extends StatefulWidget {
const FirstChild({Key? key}) : super(key: key);

@override
State<FirstChild> createState() => _FirstChildState();
}

class _FirstChildState extends State<FirstChild> {
@override
Widget build(BuildContext context) {
...

如果您发现自己想要编辑此默认语法,这表明您需要找到更好的方法来实现您正在尝试做的任何事情。如果您需要从 Widget 外部访问在 Widget 中声明的 function,则应在其他地方声明该函数。

综上所述,除非您需要 setStateinitState 或其他生命周期函数,否则您不需要 StatefulWidget首先。所有这些类都可以是Stateless

在没有完整的状态管理解决方案的情况下使 DealsNotifier 类全局可访问的一种简单方法是将其设为 static 类。


class DealsNotifier {
static ValueNotifier<List<Food>> dealList = ValueNotifier([]);
static ValueNotifier<List<Food>> menuitemList = ValueNotifier([]);
static ValueNotifier<List<Map<String, dynamic>>> categoryList =
ValueNotifier([]);

static void updateDealsList(List<Food> list) {
dealList.value = list;
print('DEAL LIST IN CLASS: ${dealList}');
}

static void updateMenuList(List<Food> list) {
menuitemList.value = list;
print('PRICE CHANGE: ${menuitemList.value[2].price}');
print('MENU ITEM LIST IN CLASS: ${menuitemList}');
}

static void updateCategoryList(List<Map<String, dynamic>> catList) {
categoryList.value = catList;
print('DEAL LIST IN CLASS: ${categoryList}');
}

static List<Food> getDealList() {
return dealList.value;
}

static List<Food> getMenuitemList() {
return menuitemList.value;
}

static List<Map<String, dynamic>> getCategoryList() {
return categoryList.value;
}
}

然后,当您需要传入 valueListenable 时,您可以通过 DealsNotifier.menuitemlist 访问,它始终是同一个实例。

return ValueListenableBuilder(
valueListenable: DealsNotifier.menuitemList,
builder: (context, List<Food> value, widget) {
print('MENUITEM LIST UPDATED: ${value}');
return HotkeysMenuItemsWidget(
key: menuItemsKey,
currentMenu: currentCat != null ? value : [],
);
},
);

这是所有这些类的 Stateless 版本,在任何需要 UI 更新的地方,您都可以使用 ValueListenableBuilder 并传入 DealsNotifier.whicheverVariableYouWantToListenTo valueListenable。然后调用 DealsNotifier 类中的任何相关方法,即。 DealsNotifier.updateMenuList([])

并且您没有共享您的 HotkeysMenuItemsWidget,但如果您希望在此处查看 UI 中的更改,那么应该在此处显示 ValueListenableBuilder。它目前在小部件树中的位置太高,它需要做的就是重新呈现该 Widget 中的列表,您不需要/想要整个重新构建 HotkeysMenuItemsWidget 来自父小部件。


class FirstChild extends StatelessWidget {
const FirstChild({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return ValueListenableBuilder( // this should be inside HotkeysMenuItemsWidget
valueListenable: DealsNotifier.menuitemList,
builder: (context, List<Food> value, widget) {
print('MENUITEM LIST UPDATED: ${value}');
return HotkeysMenuItemsWidget(
key: menuItemsKey,
currentMenu: currentCat != null ? value : [],
);
},
);
}
}

class SecondChild extends StatelessWidget {
const SecondChild({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {
DealsNotifier.updateMenuList([]);
},
child: Text(
'UPDATE',
maxLines: 2,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 12,
),
),
);
}
}

class HotKeysWidget extends StatelessWidget {
const HotKeysWidget({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: [
FirstChild(),
SecondChild(),
],
),
);
}
}

关于flutter - 更新通知程序值后未调用 ValueListenableBuilder 构建器方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72585555/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com