使用 Equatable 类与 flutter_bloc

23
为什么我们需要在flutter_bloc中使用Equatable类?还有,我们用props做什么?以下是在Flutter中使用bloc模式制作状态的示例代码。
为什么需要使用Equatable类与flutter_bloc一起使用?另外,props的作用是什么?下面是在Flutter中使用bloc模式创建状态的示例代码。
    abstract class LoginStates extends Equatable{}
    
    class LoginInitialState extends LoginStates{
      @override
      List<Object> get props => [];
    
    }

3个回答

28

为了比较数据,我们需要使用Equatable。它内部重写了==hashCode,这样可以节省很多样板代码。在Bloc中,我们必须将States and Events类扩展到Equatable以使用此功能。

 abstract class LoginStates extends Equatable{}

所以,这意味着LoginStates不会发出重复的调用,并且不会在相同状态发生时重建小部件。

定义状态:

class LoginInitialState extends LoginStates {}

使用 props 定义 State:

当我们希望将 State 与在 props 列表中声明的值进行比较时,需要声明 props

class LoginData extends LoginStates {
  final bool status;
  final String userName;
  const LoginData({this.status, this.userName});
  @override
  List<Object> get props => [this.status, this.userName];
}

如果我们从列表中删除用户名,保留像[this.status]这样的列表,那么State将只考虑status字段,避免username字段。这就是为什么我们使用props来处理状态更改的原因。 Bloc Stream用法: 由于我们使用了State with Equatable,它会比较旧状态数据和新状态数据。例如,让我们看下面的例子,这里的LoginData只会构建一个小部件,这将避免第二次调用,因为它是重复的。
@override
Stream<LoginStates> mapEventToState(MyEvent event) async* {
  yield LoginData(true, 'Hello User');
  yield LoginData(true, 'Hello User'); // This will be avoided
}

7
上面的回答已经清楚了状态的问题,但事件呢?为什么我们需要对事件实现Equatable协议?Bloc允许多次传递相同的事件。 - Iducool
事件扩展Equatable有几个原因:-支持事件转换器/运算符,如“distinct” -易于测试/比较 -一致性*基于来自felangel包在此问题中的回复 https://github.com/felangel/bloc/issues/3277 - Sprint

13

我们正在使用Equatable包,以便我们可以比较类的实例而无需手动覆盖“==”和hashCode。

Equatable类允许我们比较两个对象是否相等。

这是Equatable的示例。假设我们有以下类:

class Person {
  final String name;

  const Person(this.name);
}

我们可以这样创建Person的实例:

void main() {
  final Person bob = Person("Bob");
}

接下来,如果我们尝试在生产代码或测试中比较两个Person实例,我们会遇到问题。

print(bob == Person("Bob")); // false
为了能够比较两个 Person 实例,我们需要更改我们的类以覆盖 == 和 hashCode 方法,代码如下:
class Person {
  final String name;

  const Person(this.name);

  @override
  bool operator ==(Object other) =>
    identical(this, other) ||
    other is Person &&
    runtimeType == other.runtimeType &&
    name == other.name;

  @override
  int get hashCode => name.hashCode;
}

现在如果我们再次运行以下代码:

print(bob == Person("Bob")); // true

它将能够比较不同的Person实例。

这样,当覆盖"=="和hashCode时,您就不必浪费时间编写大量样板代码。

使用Equatable就像

class Person extends Equatable

当你尝试在bloc中使用可变状态时,如果没有使用Equatable会遇到问题。这使得资源不可变,并降低了性能。复制对象比改变属性更加昂贵。

如果我解释得不够清楚,阅读此文可能会有所帮助。


但是为什么我们需要在flutter_bloc中使用它呢?仅当我们需要在bloc中表达(state is some state)时才需要。 - Osama Mohammed
谢谢,我应该在每个类中实现(props)并添加我的状态,还是从性能角度来看不重要? - Osama Mohammed
是否有一个使用 equatable 实现同样功能的示例呢?将它们并排比较可以更好地改进这个答案。 - dKen

2
Equatable会为你重写==和hashCode,因此你不必浪费时间编写大量样板代码。
还有其他包可以为您生成样板代码;但是,您仍然需要运行代码生成步骤,这不是理想的。
使用Equatable不需要代码生成,我们可以更多地专注于编写令人惊叹的应用程序,而不是单调乏味的任务。propsequatablegetter,它获取我们想要的属性
虽然不需要专注于它,我只是在props getter中放置了属性。这并不重要,但我建议您在这里阅读更多信息。

但是为什么我们需要在flutter_bloc中使用它呢?只有当我们需要在bloc中使用(state is some state)这样的示例时才需要。 - Osama Mohammed
就像我之前所说的,使用它可以避免编写大量样板代码,这就像我们为什么使用HTTP进行API请求或文本样式如何工作一样,你可以找到答案,但对你并没有帮助。 - Yaya
3
不好意思,你的例子不正确,因为我需要知道为什么我们要使用它,你说覆盖 == 和 hashCode,但是你仍然没有回答我的问题,因为我的问题是关于为什么我们需要在 bloc (flutter_bloc) 中覆盖它们。所以为什么我们需要在 bloc 中覆盖 == 和 hashCode? :) - Osama Mohammed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接