我在我的混和颤振项目中使用了状态管理。
我有一个模型类,它管理对象列表及其排序顺序。排序顺序只是一个带有字段名称的String,应该使用该字段进行排序。
UI是一个包含ListView.separated的Slidable。您可以修改、复制或删除列表中的条目。在列表的顶部是DropDownButton,它允许选择一个字段来对列表进行排序。
以下是屏幕的相关部分:

Widget是无状态的,在build方法中有两个观察者,如下所示:
var ccOverviewList = watchOnly((CcListManager ccListManager) => ccListManager.creditCardOverviewList);
var sortProperty = watchOnly((CcListManager ccListManager) => ccListManager.sortProperty);当用户选择一个不同的属性对列表进行排序时,我会在我的模型类中调用一个方法,然后调用notifyListener。这对于存储的排序属性很好,但是当列表被修改时不起作用。onChanged的DropDownButton处理程序如下所示:
onChanged: (String? newValue) {
GetIt.I<CcListManager>().sortProperty = newValue!;
},模型中的实现(CcListManager):
class CcListManager extends ChangeNotifier {
var _sortProperty = 'Name';
set sortProperty(String val) {
_sortProperty = val;
_sortCreditCardOverview();
debugPrint('Notifying listeners...');
notifyListeners();
}
String get sortProperty => _sortProperty;
List<CreditCardOverview> _creditCardOverviewList = /*<CreditCardOverview>*/[];
set creditCardOverviewList(List<CreditCardOverview> val) {
_creditCardOverviewList = val;
debugPrint('Notifying listeners...');
notifyListeners();
}
List<CreditCardOverview> get creditCardOverviewList => _creditCardOverviewList;
}当_sortProperty更改并调用notifyListeners时,我可以看到调用了带有ListView的小部件的.build()方法。
,但是当我修改列表_creditCardOverviewList上的时,build()方法是而不是调用的,因此列表不会更新。下面是delete操作的代码:
void removeCreditCardFromOverview(String creditCardId) {
debugPrint('CcListManager.removeCreditCardFromOverview()');
var pos = _creditCardOverviewList.indexWhere((element) => element.creditCardLocalId == creditCardId);
if (pos >= 0) {
_creditCardOverviewList.removeAt(pos);
debugPrint('Notifying listeners...');
notifyListeners();
}
}我不知道为什么适用于原语类型,但不适用于集合。在我看来,在notifyListeners()内部,它会检查属性的值是否真的发生了变化,不知道是否承认,列表中的元素或其长度已经改变,因此不会通知已注册的侦听器。
我也不知道这是get_it / get_it_mixin插件的问题还是ChangeNotifier / notifyListeners的问题。
知道这里出了什么问题吗?
发布于 2022-01-05 09:44:44
好的,我自己发现了问题。这也是一年多前使用提供商的人经历过的事情。它看起来像是notifyListeners检查这个值是否真的改变了。看起来他们依赖于==运算符来获取列表。这个操作符做了,而不是,对列表中的每个成员进行了深入的比较。因此,解决方案是使用.from()命名构造函数重新创建整个列表。那么它就会像预期的那样工作。因此,上述删除代码需要更改如下:
void removeCreditCardFromOverview(String creditCardId) {
var pos = _creditCardOverviewList.indexWhere((element) => element.creditCardLocalId == creditCardId);
if (pos >= 0) {
_creditCardOverviewList.removeAt(pos);
creditCardOverviewList = List.from(_creditCardOverviewList);
}
}notifyListeners由creditCardOverviewList的设置者调用。
https://stackoverflow.com/questions/70576332
复制相似问题