改变flutter_bloc中的`currentState`属性

Posted

技术标签:

【中文标题】改变flutter_bloc中的`currentState`属性【英文标题】:mutate `currentState` property in flutter_bloc 【发布时间】:2019-11-22 02:58:24 【问题描述】:

我有一个颤动的应用程序,我在 listView 小部件中按姓名和销售人员显示员工列表。我为每个员工设置了两个按钮来增加或减少他们的销售额。

我正在使用flutter_bloc 进行状态管理。

这里是 Employee 类。

class Employee extends Equatable 
  int _id;
  String _name;
  double _salery;

  Employee(this._id, this._name, this._salery);

  // setters
  set id(int id) 
    this._id = id;
  

  set name(String name) 
    this._name = name;
  

  set salery(double salery) 
    this._salery = salery;
  

  // getters
  int get id => this._id;
  String get name => this._name;
  double get salery => this._salery;

这是作为事件的类。

@immutable
abstract class EmployeeEvent 
  final int _index;
  EmployeeEvent(this._index);

  int get index => this._index;


class IncrementEvent extends EmployeeEvent 
  IncrementEvent(int index) : super(index);


class DecrementEvent extends EmployeeEvent 
  DecrementEvent(int index) : super(index);

这是处理状态的 bloc 类。

class EmployeeBloc extends Bloc<EmployeeEvent, List<Employee>> 
  @override
  List<Employee> get initialState => [
        Employee(1, 'Employee One', 10000.0),
        Employee(2, 'Employee Two', 10000.0),
        Employee(3, 'Employee Three', 10000.0),
        Employee(4, 'Employee Four', 10000.0),
        Employee(5, 'Employee Five', 10000.0),
      ];

  @override
  Stream<List<Employee>> mapEventToState(EmployeeEvent event) async* 
    // I have checked, the control reaches over here.
    double currentSalery = currentState[event.index].salery;
    if (event is IncrementEvent) 
      // Increments the salery when user presses the increment button
      currentState[event.index].salery = currentSalery + (currentSalery * 0.2);
     else if (event is DecrementEvent) 
      currentState[event.index].salery = currentSalery - (currentSalery * 0.2);
    
    print(currentState[event.index].salery); // even prints the incremented / decremented salery.
    yield currentState;
  

屈服后,不会调用小部件类中的BlocBuilder

如果我像这样更改方法,那么它会调用BlocBuilder,但我不能在特定索引处增加或减少员工的销售额。

@override
Stream<List<Employee>> mapEventToState(EmployeeEvent event) async* 
  if (event is IncrementEvent) 
    yield currentState;
   else if (event is DecrementEvent) 
    yield currentState;
  

我如何在特定指数增加或减少特定员工的销售额?

【问题讨论】:

【参考方案1】:

您的主要问题是您没有任何代表您的状态的类。所以首先你应该创建需要的状态。您可以使用blocwebsite中提供的简单示例。

为了全球理解:

BlocBuilder 将仅在这些情况下重建(使用 equatable):

新旧状态的实例运行时类型不同 新旧状态的实例是相同的实例类型,它将通过调用==深入比较前一个和新状态的所有嵌套属性以了解发生了什么变化。 您还可以使用您在创建时提供的conditional 属性函数。

如果你想使用相同的实例,你可以扩展Equatable(来自equatable 包here)或做同样的事情。 (thismedium post 可以帮到你)。

你可以这样做:

abstract class EmployeeState extends Equatable 
  EmployeeState([List props = const []]) : super(props);

  @override
  String toString() => '$runtimeType';


class EmployeeLoaded extends EmployeeState
  EmployeeLoaded(this.employees):super([employees])

  final List<Employee> employees;


如需更多信息/帮助,您可以拨打bloc gitter。

【讨论】:

【参考方案2】:

flutter bloc 要求您生成一个新的状态实例,而不是修改 currentState。

所以我在以下类中进行了以下更改。

class Employee extends Equatable 
  int id;
  String name;
  double salery;

  Employee(this.id, this.name, this.salery) : super([id, name, salery]);

  Employee copyWith(
    String name,
    double salery,
  ) 
    return Employee(this.id, name ?? this.name, salery ?? this.salery);
  

  @override
  String toString() 
    return 'Employee  id: $id, name: $name, salery: $salery ';
  

修改了 mapEventToState 方法并添加了一个帮助方法来更新列表属性。

@override
  Stream<List<Employee>> mapEventToState(EmployeeEvent event) async* 
    yield this.updateList(event);
  

  Stream<EmployeeState> updateList(EmployeeEvent event) async* 
    final id = (currentState as EmployeeLoaded).employee[event.index].id;

    List<Employee> employeeUpdate =
        (currentState as EmployeeLoaded).employee.map((employee) 
      if (employee.id == id) 
        return employee.copyWith(
            salery: (event is IncrementEvent)
                ? employee.salery + 200
                : employee.salery - 200);
      
      return employee;
    ).toList();

    print((currentState as EmployeeLoaded).employee == employeeUpdate);
    print(currentState == EmployeeLoaded(employeeUpdate));

    yield EmployeeLoaded(employeeUpdate);
  

【讨论】:

以上是关于改变flutter_bloc中的`currentState`属性的主要内容,如果未能解决你的问题,请参考以下文章

flutter_bloc :使 initialState 方法异步

如何在我的项目中应用flutter_bloc?

使用 flutter_bloc 库有啥缺点

由于某种原因不能使用flutter_bloc

从 v7.2.1 迁移到 flutter_bloc v 8.0.0 后不会触发 flutter_bloc 事件

flutter_bloc/provider RepositoryProvider vs Provider