我有一个非常简单的系统。它基本上由某个屏幕的主视图模型组成,该模型创建了注入到一些子部件上的子视图模型。
该主视图模型具有以下相关属性:
List<ChildrenViewModel> childrenViewModels;
int numberOfChildren() { return childrenViewModels.length; }
ChildrenViewModel childAt(int index) { return childrenViewModel[index]; }
void selectIfPossible(ChildrenViewModel child) {
//Business Logic to check if it is possible to select
child.aCertainProperty.anotherProperty.selected = true;
notifyObservers();
}
我的主Widget确实有一个List.builder,它看起来像:
ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: numberOfChildren(),
itemBuilder: (context, index) {
return ChildWidget(
viewModel: viewModel.childAt(index));
})
}
现在我的ChildWidget如下:
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
viewModel.selectItem();
},
child: Column(
children: [
// a few widgets
Image(
image: AssetImage(child.aCertainProperty.anotherProperty.selected
? selectedImage
: unselectedImage)),
),
// a few widgets
],
),
);
在我的ChildViewModel上,onTap只执行以下操作:
void selectItem() {
parentViewModel.selectIfPossible(this); //parentViewModel is the Main View Model on top
}
原理很简单。用户点击列表上的某个项目,在主视图模型上检查一些业务逻辑,然后通知观察者项目已更新,列表相应地更新项目。
然而,这根本不起作用。通过逐步调试,我可以看到视图模型中的数据是正确的,但是ListView.Builder永远不会返回更新的小部件。不知何故,在使用断点时,我可以一步一步地进行,直到itemCount: numberOfChildren()
,但它永远不会前进到构建器本身,以便它可以返回更新的小部件。有没有人有任何提示,我做错了什么,我可以。改变来解决我的问题
先谢谢你了!
我已经尝试了我能想到的一切。它“工作”的唯一方法是,如果我把观察者放在Widget上,它是拥有ListView的Widget的父级,并强制构建ListView的整个树。然而,这样做的列表确实滚动回到顶部,这是可怕的用户体验。
1条答案
按热度按时间pqwbnv8z1#
如果我理解你的应用程序的权利,你只更新这个选择:
如果是这样,试着找到一个关键,你可以提供给它。就像我评论中的链接。您必须提供唯一的密钥。但也是小部件持有的形象必须是有状态的!!!.
如果你想重新构建整个Listview,你必须检查Widget的变化,它正在构建ListView. builder。然后给予每个Item一个唯一的key,如下所示:
但这里的小部件是建设Listview必须是一个statefull!