简体   繁体   中英

Update of the not immediate state in Example Counter - BloC Flutter

My pubspec.yml:

  bloc: ^4.0.0
  flutter_bloc: ^4.0.0
  equatable: ^1.2.5

I created my 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),
            ),
          ],
        ),
      ),
    );
  }
}

Then my question is:

Inside FloatingActionButton, I increment value to my state; But I print before increment and after increment and the state is the same value; test 0 = 0; test 1 = 0; Why? In the screen reflect my value, but not immediately in my prints inside FloatingActionButton;

After I tested this:

            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());
              },
              child: Icon(Icons.add_circle),
            ),
    ```

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

That is because of how the scheduler works. Dart code is executed on a single event loop. The order in which instructions are executed is influenced by await .

Without the Future.delayed (you could have used Future.delayed(Duration.zero) by the way) when code in the onPressed lambda is executed entirely sequentially. The add method calls mapEventToState which is an async method (generator really). When Dart encounters such a method it will schedule it for later execution and progress to the next instruction. Therefor you will see 0 twice.

This changes when you add an await call like your Future.delayed . Dart will then stop and see what else it can run. In this case the mapEventToState . It will run that one and after it will continue on with the remainder of the onPressed lambda. That is why you see 1 with the awaited Future.delayed .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM