在我们项目中有这么一个场景,有一个树型结构的字典列表,需要实现多选功能。我的实现思路呢,是自定义了一个DictIndexPath
下标类,里面包含两个属性:行section
、列row
,然后通过一个List来存储选择的下标类。
// 下标类
class DictIndexPath {
int section;
int row;
DictIndexPath(this.section, this.row);
@override
String toString() {
return 'section: $section, row: $row';
}
}
// 存储
List<DictIndexPath> _selectTemp = [];
然后在选择字典项的时候,根据树形结构计算行列的值,然后判断是否选中:
int section = ...
int row = ...
DictIndexPath indexPath = DictIndexPath(section, row);
if (_selectTemp.contains(indexPath)) {
_selectTemp.remove(indexPath);
} else {
_selectTemp.add(indexPath);
}
但是呢,理想很丰满,现实很骨感,这么做并不能实现我想要的效果。结果呢会发现contains方法返回的一直都是false,从而重复添加到_selectTemp
里面。
这是因为DictIndexPath
在初始化的时候会生成一个唯一的hashCode
,虽然section和row是一样的,但是hashCode不同,导致生成的每一个indexPath都是不一样的。
所以呢要重写hashCode的获取方法,使相同的section和row的时候,hashCode保持一致。下面是我所采用的方式:
@override
int get hashCode {
return section * 100 + row;
}
但是呢,在选择字典项的时候还是不行,还是会重复添加。
于是就想着是不是contains
方法的原因。通过查看源码发现,contains
方法很简单,就是遍历集合,然后判断是否相等。
bool contains(Object? element) {
for (E e in this) {
if (e == element) return true;
}
return false;
}
于是就想起曾经看过的文章,需要重写==
操作符,来实现判断两个对象是否相等。想起来就干啊,于是就在DictIndexPath
类中增加了我自己的操作符重载。
operator ==(other) {
if (other is! DictIndexPath) {
return false;
}
return section == other.section && row == other.row;
}
再次尝试选择字典项,终于实现目标了。
最终的DictIndexPath
类如下:
class DictIndexPath {
int section;
int row;
DictIndexPath(this.section, this.row);
@override
String toString() {
return 'section: $section, row: $row';
}
@override
int get hashCode {
return section * 100 + row;
}
operator ==(other) {
if (other is! DictIndexPath) {
return false;
}
return section == other.section && row == other.row;
}
}