在示例计数器中更新非立即状态-BloC Flutter

问题描述

我的pubspec.yml:

  bloc: ^4.0.0
  Flutter_bloc: ^4.0.0
  equatable: ^1.2.5

我创建了CounterBloc:

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

  @override
  Stream<int> mapEventToState(event) async* {
    if (event.status == EventStatus.INCREMENT) {
      yield state + event.value;
    } else if (event.status == EventStatus.DECREMENT) {
      yield state - event.value;
    }
  }
}
enum EventStatus { INCREMENT,DECREMENT }

class CounterEvent {
  final int value;
  final EventStatus status;

  const CounterEvent({this.value,this.status});
}
void main() => runApp(Counterapp());

class Counterapp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BLoC Demo',home: BlocProvider<CounterBloc>(
        create: (context) => CounterBloc(),lazy: false,child: TestBlocWidget(),),);
  }
}
class TestBlocWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counterBloc = BlocProvider.of<CounterBloc>(context);
    return Scaffold(
      body: Center(
        child: BlocBuilder<CounterBloc,int>(
          builder: (ctx,state) {
            return Text(
              'count: $state',style: TextStyle(fontSize: 28),);
          },floatingActionButton: Align(
        alignment: Alignment.bottomright,child: Column(
          mainAxisSize: MainAxisSize.min,children: [
            FloatingActionButton(
              onpressed: () async {
                print("test 0 = " + counterBloc.state.toString());
                counterBloc.add(CounterEvent(value: 1,status: EventStatus.INCREMENT));
                print("test 1 = " + counterBloc.state.toString());
              },child: Icon(Icons.add_circle),FloatingActionButton(
              onpressed: () {
                print("test 2 = " + counterBloc.state.toString());
                counterBloc
                    .add(CounterEvent(value: 1,status: EventStatus.DECREMENT));
                print("test 3 = " + counterBloc.state.toString());
              },child: Icon(Icons.remove_circle),],);
  }
}

然后我的问题是:

在FloatingActionButton里面,我将value递增到我的状态; 但是我在增量之前和之后打印,并且状态是相同的值; 测试0 = 0; 测试1 = 0; 为什么? 在屏幕上反映出我的价值,但没有立即在FloatingActionButton内的照片中反映出来;

我对此进行了测试:

            FloatingActionButton(
              onpressed: () async {
                print("test 0 = " + counterBloc.state.toString());
                counterBloc
                    .add(CounterEvent(value: 1,status: EventStatus.INCREMENT));
                await Future.delayed(Duration(milliseconds: 0));
                print("test 1 = " + counterBloc.state.toString());
              },```

Note: I put "await Future.delayed",after my CounterBloc,with value 0 in my FloatingActionButton;
Works;
test 0 = 0;
test 1 = 1;

解决方法

那是因为调度程序如何工作。 Dart代码在单个事件循环上执行。执行指令的顺序受await的影响。

Future.delayed lambda中的代码完全顺序执行时,没有Future.delayed(Duration.zero)(您可能已经使用onPressed)。 add方法调用mapEventToState,这是一个异步方法(实际上是生成器)。当Dart遇到这样的方法时,它将安排它以供以后执行并前进到下一条指令。因此,您将两次看到0

当您添加await之类的Future.delayed呼叫时,这种情况会改变。然后Dart将停止并查看它还能运行什么。在这种情况下,mapEventToState。它会运行那个,然后继续处理onPressed lambda的其余部分。这就是为什么您看到1和期待的Future.delayed的原因。