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

Posted

技术标签:

【中文标题】更新示例计数器中的非立即状态 - BloC Flutter【英文标题】:Update of the not immediate state in Example Counter - BloC Flutter 【发布时间】:2021-01-08 01:25:15 【问题描述】:

我的 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 内部,我将值递增到我的状态; 但是我在增量之前和之后打印并且状态是相同的值; 测试 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());
              ,
              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;

【问题讨论】:

【参考方案1】:

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

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

当您添加await 调用(如Future.delayed)时,这种情况会发生变化。 Dart 然后会停下来看看它还能运行什么。在这种情况下,mapEventToState。它将运行那个,之后它将继续使用 onPressed lambda 的其余部分。这就是为什么您会看到 1 和期待已久的 Future.delayed

【讨论】:

以上是关于更新示例计数器中的非立即状态 - BloC Flutter的主要内容,如果未能解决你的问题,请参考以下文章

选择不依赖于状态的正确颤振块小部件

Flutter BLoC:在父 Widget 更新时维护子状态

我正在借助 bloc(cubit)创建异步计数器应用程序,每次计数器返回 0 时我都会发出加载状态

我正在使用 BLOC 制作一个简单的计数器应用程序,但是当我增加/减少计数器时,我的计数器没有更新?我使用 BlocBuilder 构建 UI

Flutter Bloc - Flutter Bloc 状态未更新

如何在登录页面中使用 BLoC