state as class 是否需要 SatefulWidget?

Does state as class requires SatefulWidget?

我正在尝试学习 flutter 中的 bloc 模式并使用 bloc 框架创建一个示例应用程序。该应用程序是一个计数器,在计数器文本字段下方有两个按钮。单击 TrueFalse 按钮后,我现在只是分别递增和递减计数器。

我注意到,如果我在实施 Bloc 模式时使用 class 作为状态,那么我必须写 StatefulWidget。相反,如果我只使用 int 那么即使使用 StatelessWidget 也能正常工作。

所以,在实现相同示例时,使用 class 作为状态,使用原始数据类型作为状态,这让我感到困惑。

这是我的代码 CounterBloc 状态定义为 class CounterState

的代码
enum CounterEvent { Increment, Decrement }

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterState counterState = new CounterState(counter: 0);
  @override
  // TODO: implement initialState
  CounterState get initialState => counterState;

  @override
  Stream<CounterState> mapEventToState(CounterEvent event) async* {
    // TODO: implement mapEventToState

    switch (event) {
      case CounterEvent.Decrement:
        counterState.decrementCounter();
        yield counterState;

        break;

      case CounterEvent.Increment:
        counterState.incrementCounter();
        yield counterState;

        break;
    }
  }
}

我的CounterState定义如下

class CounterState {
  int counter = 0;

  CounterState({this.counter});

  void incrementCounter() {
    counter++;
  }

  void decrementCounter() {
    counter--;
  }
}

这就是我在按下按钮时调度事件的方式

onPressed: () {
  setState(() {
    counterBloc.dispatch(CounterEvent.Increment);
  }); 

StatefulWidget

内与 UI 绑定
 BlocBuilder<CounterBloc, CounterState>(builder: (context, snapshot) {
       .....
                child: Text(
                  snapshot.counter.toString(),
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    fontSize: 25.0,
                    color: Colors.white,
                  ),
                ),

     .....
 });

现在,如果我使用 int 作为状态,那么它在 StatelessWidget 中工作正常。

这是状态为整数的 CounterBloc

enum CounterEvent { Increment, Decrement }

class CounterBloc extends Bloc<CounterEvent, int> {
  @override
  // TODO: implement initialState
  int get initialState => 0;

  @override
  Stream<int> mapEventToState(CounterEvent event) async* {
    // TODO: implement mapEventToState

    switch (event) {
      case CounterEvent.Decrement:

        yield currentState -1;;

        break;

      case CounterEvent.Increment:

        yield currentState +1;;

        break;
    }
  }
}

更新

enum CounterEvent { Increment, Decrement }

class CounterBloc extends Bloc<CounterEvent, CounterState> {
  @override
  // TODO: implement initialState
  CounterState get initialState => CounterState(counter: 0);

  @override
  Stream<CounterState> mapEventToState(CounterEvent event) async* {
    // TODO: implement mapEventToState

    switch (event) {
      case CounterEvent.Decrement:
        CounterState counterState = CounterState(counter: currentState.counter);
        counterState.decrementCounter();
        yield counterState;

        break;

      case CounterEvent.Increment:
        CounterState counterState = CounterState(counter: currentState.counter);
        counterState.incrementCounter();

        yield counterState;

        break;
    }
  }
}

在@Rémi Rousselet 的评论的帮助下解决了这个问题。现在我每次都通过新状态

问题不在于它是否是 class,而是关于不变性。

使用bloc,你的状态必须是不可变的。您不应该修改以前的状态,而是创建一个新的修改状态。