作为类的状态是不是需要 SatefulWidget?

Posted

技术标签:

【中文标题】作为类的状态是不是需要 SatefulWidget?【英文标题】:Does state as class requires SatefulWidget?作为类的状态是否需要 SatefulWidget? 【发布时间】:2019-12-24 13:44:21 【问题描述】:

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

我注意到的是,如果我在实现Bloc 模式时使用类作为状态,那么我必须编写StatefulWidget。相反,如果我只使用int,那么即使使用StatelessWidget 也可以正常工作。

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

这是我的代码 CounterBloc 代码,状态定义为类 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 的评论的帮助下解决了这个问题。现在我每次都在传递新状态

【问题讨论】:

【参考方案1】:

问题不在于它是否是一个类,而在于不变性。

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

【讨论】:

以上是关于作为类的状态是不是需要 SatefulWidget?的主要内容,如果未能解决你的问题,请参考以下文章

如果派生类作为基类返回,如何访问派生类的方法?

通过Static 字段来维护状态是不是一个好主意

java 对象和类

为啥我可以在 Qt 5.5.1 中使用 QSerialPort* 作为临时变量而不是作为类的成员?

类的加载与ClassLoader的理解

NumPy 矩阵类的弃用状态