为什么我们应该在Flutter Bloc中使用Equatable?

bvjveswy  于 2023-03-24  发布在  Flutter
关注(0)|答案(2)|浏览(242)

我知道Equatable可以帮助比较两个对象示例,而不需要手动操作。但是在Flutter Bloc中,我可以在哪里使用它呢?
下面是Equatable的用法示例:
在哪些方面有用?

abstract class TodosState extends Equatable {
  const TodosState();

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

class TodosLoadInProgress extends TodosState {}

class TodosLoadSuccess extends TodosState {
  final List<Todo> todos;

  const TodosLoadSuccess([this.todos = const []]);

  @override
  List<Object> get props => [todos];

  @override
  String toString() => 'TodosLoadSuccess { todos: $todos }';
}

class TodosLoadFailure extends TodosState {}
jxct1oxe

jxct1oxe1#

当涉及到流时,对象和数据比较总是很难进行,因为我们需要基于它来决定状态更新。我们需要Equatable,因为它在内部覆盖==hashCode,这节省了大量的样板代码。在Bloc中,我们必须将Equatable扩展到States and Events类才能使用此功能。

abstract class TodosState extends Equatable {}

因此,这意味着TodosState不会进行重复调用,并且如果发生相同的状态,也不会重新构建小部件。
让我们看看props在Equatable中的用法,以及它的特殊之处

不带 prop 定义State:

class TodosLoadSuccess extends TodosState {}

使用props定义状态:

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

class TodosLoadSuccess extends TodosState {
  final String name;
  final List<Todo> todos;
  const TodosLoadSuccess([this.name, this.todos = const []]);

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

 }

如果我们从列表中删除名字并保留一个像[this.todos]这样的列表,那么State将只考虑todos字段,而不考虑name字段。这就是为什么我们使用props来处理State更改的原因。

分块流使用情况:

当我们扩展State with Equatable时,它会比较旧的状态数据和新的状态数据。例如,让我们看看下面的例子,TodosState只会构建一次小部件,这将避免第二次调用,因为它是重复的。

@override
Stream<TodosState> mapEventToState(MyEvent event) async* {
  final List<Todo> todos = [Todo(), Todo()];
  yield TodosLoadSuccess(todos);
  yield TodosLoadSuccess(todos); // This will be avoided
}
mcvgt66p

mcvgt66p2#

我认为这对于比较BlocBuilder中的状态很有用。
下面的代码是使用Equatable的一个很好的例子。

if(state is [Some State])
@override
Widget build(BuildContext context) {
  return BlocBuilder<SongsSearchBloc, SongsSearchState>
    bloc: BlocProvider.of(context),
    builder: (BuildContext context, SongsSearchState state) {
      if (state is SearchStateLoading) {
        return  CircularProgressIndicator();
      }
      if (state is SearchStateError) {
        return Text(state.error);
      }
      if (state is SearchStateSuccess) {
        return state.songs.isEmpty
            ? Text(S.EMPTY_LIST.tr())
            : Expanded(
                child: _SongsSearchResults(
                  songsList: state.songs,
                ),
              );
      } else {
        return  Text(S.ENTER_SONG_TITLE.tr());
      }
    },
  );
}

相关问题