state as class 是否需要 SatefulWidget?
Does state as class requires SatefulWidget?
我正在尝试学习 flutter 中的 bloc 模式并使用 bloc
框架创建一个示例应用程序。该应用程序是一个计数器,在计数器文本字段下方有两个按钮。单击 True
和 False
按钮后,我现在只是分别递增和递减计数器。
我注意到,如果我在实施 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
,你的状态必须是不可变的。您不应该修改以前的状态,而是创建一个新的修改状态。
我正在尝试学习 flutter 中的 bloc 模式并使用 bloc
框架创建一个示例应用程序。该应用程序是一个计数器,在计数器文本字段下方有两个按钮。单击 True
和 False
按钮后,我现在只是分别递增和递减计数器。
我注意到,如果我在实施 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
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
,你的状态必须是不可变的。您不应该修改以前的状态,而是创建一个新的修改状态。