Flutter Bloc未重建状态

时间:2020-03-04 16:09:20

标签: flutter dart flutter-bloc

我已经用flutter_bloc包实现了一个简单的集团:

class MainBloc extends Bloc<MainEvent, MainState> {
  @override
  MainState get initialState => Init();

  @override
  Stream<MainState> mapEventToState(MainEvent event) async* {
    if (event is Event) {
      yield* _mapEventToState();
    }
  }

  Stream<MainState> _mapEventToState() async* {
    final loadState = Load();
    print("Yield state: $loadState");
    yield loadState;
    await sleep(Duration(seconds: 1));
    final initState = Init();
    print("Yield state: $initState");
    yield initState;
  }
}

发生以下事件:

abstract class MainEvent {}

class Event extends MainEvent {}

和这种状态:

abstract class MainState {}

class Load extends MainState {}

class Init extends MainState {}

我的用户界面如下:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Material App',
      home: BlocProvider(
        create: (context) => MainBloc(),
        child: Scaffold(
          appBar: AppBar(),
          body: BlocBuilder<MainBloc, MainState>(
            builder: (context, state) {
              print("Build state: $state");
              if (state is Init) {
                return MaterialButton(
                  onPressed: () => BlocProvider.of<MainBloc>(context).add(Event()),
                  child: Text("Press"),
                );
              } else {
                return Text("Loading");
              }
            },
          ),
        ),
      ),
    );
  }
}

不幸的是,如果我添加带有MaterialButton的Event,则将忽略Load()状态。 UI不会重建加载状态。输出如下:

I / flutter(1955):屈服状态:“负载”的实例

I / flutter(1955):屈服状态:'Init'的实例

I / flutter(1955):构建状态:“ Init”的实例

1 个答案:

答案 0 :(得分:1)

这是因为您正在使用await sleep(Duration(seconds: 1));await语句在这里没有用,它是一个同步函数)。

sleep函数暂停执行主线程,这意味着它还将阻止应用程序主页的重建,因此由于新的{{ 1}}状态。冻结应用程序结束后,它会立即进入新状态,这就是为什么您永远看不到加载页面的原因。

改为使用Load,这将暂停执行其他await Future.delayed(Duration(seconds: 1));函数,但不会阻塞主线程,因此您的MainPage会得到重建。