为什么我的 indexOf 输出 -1 会抖动?

why does my indexOf output -1 in flutter?

class Task{
  String name;
  bool isDone;

  Task({this.name, this.isDone = false});

}

class TaskData{
  List<Task> tasks = [
    Task(name: 'Buy milk'),
    Task(name: 'Buy eggs'),
    Task(name: 'Buy bread')
  ];

}

void main(){

  print(TaskData().tasks.indexOf(Task(name: 'Buy milk')));
}

为什么打印 -1 ?

Flutter(Dart) 不能像比较int、strings等变量那样直接比较对象

我们必须通过检查每个变量是否相同来手动完成,然后我们才能说两个对象是否相同。

但是,我们可以使用 Equatable 包将 class 对象与其他变量进行比较。

在 pubspec.yaml 文件中添加 Equatable 包,然后如下更改 class。现在你会得到想要的输出。

class Task extends Equatable {
  String name;
  bool isDone;

  Task({this.name, this.isDone = false});

  @override
  List<Object> get props => [name, isDone];
}

您的程序打印 -1,因为您发送给 indexOf()Task 参数在 tasks 中不存在。下面的解释是与 dart 相关的,而不是与 flutter 相关的。

默认情况下,Dart 中一个对象的实例仅当它们是同一实例时才被视为等于另一个实例。在这里,您创建了两个 不同的 实例,它们可能具有相同的属性但实际上彼此独立。在这种情况下,两个任务在逻辑上是相等的,但 Dart 无法知道这一点。您的选择是:

使用 const 构造函数

Dart 中的 Const 构造函数让您可以创建作为编译时常量的实例。如果你使用这样的构造函数,Dart 会确定在你创建一个 Task 之后它的属性永远不会改变。因此,假设 Task(name: 'Buy milk') 无论如何都将始终具有另一个 Task(name: 'Buy milk') 的相同属性(它们是相等的),这将是很舒服的。在幕后,Dart 为两者使用相同的实例。要实现这一点,您必须按如下方式更改代码:

class Task {
  final String name;
  final bool isDone;

  const Task({this.name, this.isDone = false});
}

覆盖 hashCode 和 == 运算符

如果您不希望 Task 不可变,则应覆盖 Task 当前的原始相等性检查。来自 Dart 的文档:

The default hash code implementation provides an identity hash—two objects generally only have the same hash code if they are the exact same object. Likewise, the default behavior for == is identity.

If you are overriding ==, it implies you may have different objects that are considered “equal” by your class. Any two objects that are equal must have the same hash code. Otherwise, maps and other hash-based collections will fail to recognize that the two objects are equivalent.

默认的 hashCode 表示一个实例的标识,但在本例中我们希望它表示它的属性。请注意,对于具有不同属性的实例,hashCode 不应最终相同。只要保留此原则,通常如何实施并不重要。我将使用 here 提供的示例来给出可能的实现:

@override
int get hashCode {
  int result = 17;
  result = 37 * result + name.hashCode;
  result = 37 * result + isDone.hashCode;
  return result;
}

现在覆盖 == 运算符以反映更改:

 @override
  bool operator ==(dynamic other) {
    if (other is! Task) return false;
    Task task = other;
    return (task.name == name &&
        task.isDone == isDone);
  }
}

请注意,Dart 通常建议 avoid defining custom equality for mutable classes,并且按照此设计规则,我列出的第一个解决方案是最容易实现的。