0

我已经使用 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 添加我的事件,则 Load() 状态将被忽略。UI 不会重建 Load 状态。输出如下:

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

I/flutter (1955):屈服状态:“初始化”实例

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

4

1 回答 1

1

那是因为你在使用await sleep(Duration(seconds: 1));(这里await语句没用,是同步函数)。

该函数暂停主线程的执行,这意味着它也会阻止重建应用程序的主页面,因此由于新状态sleep,它没有机会重建。Load一旦冻结应用程序结束,它会立即进入一个新状态,这就是为什么你永远看不到加载页面的原因。

改为使用await Future.delayed(Duration(seconds: 1));,它会暂停函数其余部分的执行,_mapEventToState但不会阻塞主线程,因此您的 MainPage 会重新构建。

于 2020-03-04T17:10:34.053 回答