In our project, we have a scenario where we have a tree structured dictionary list and need to implement multiple selection. DictIndexPath subscript class, which contains two attributes: row Section, column row, and a List to store the selected subscript class.

/ / the subscript class
class DictIndexPath {
  int section;
  int row;

  DictIndexPath(this.section, this.row);

  @override
  String toString() {
    return 'section: $section, row: $row'; }}/ / store
List<DictIndexPath> _selectTemp = [];Copy the code

Select the row and column from the tree and check whether the dictionary is selected:

int section =.int row =.DictIndexPath indexPath = DictIndexPath(section, row);
if (_selectTemp.contains(indexPath)) {
    _selectTemp.remove(indexPath);
} else {
	_selectTemp.add(indexPath);
}Copy the code

However, the ideal is very plump, the reality is very skinny, this does not achieve the effect I want. As a result, you’ll find that the contains method always returns false, repeatedly adding to _selectTemp.

This is because DictIndexPath generates a unique hashCode when initialized. Although section and row are the same, each generated indexPath is different due to different Hashcodes.

So we need to rewrite the method of getting hashCode so that hashCode is consistent with the same section and row. Here’s how I did it:

@override
int get hashCode {
	return section * 100 + row;
}Copy the code

However, when selecting the dictionary item, it still fails and is added repeatedly.

So I wonder if this is the cause of the contains method. By looking at the source code, we found that the CONTAINS method is very simple, is to traverse the collection, and then determine whether it is equal.

bool contains(Object? element) {
    for (E e in this) {
      if (e = = element) return true;
    }
    return false;
  }Copy the code

The == operator needs to be overridden to determine whether two objects are equal. So I added my own operator overload to the DictIndexPath class.

operator = =(other) {
    if (other is! DictIndexPath) {
      return false;
    }
    return section = = other.section && row = = other.row;
}Copy the code

Try again to select the dictionary item, and there you have it.

The final DictIndexPath is as follows:

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; }}Copy the code