我已经用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”的实例
答案 0 :(得分:1)
这是因为您正在使用await sleep(Duration(seconds: 1));
(await
语句在这里没有用,它是一个同步函数)。
sleep
函数暂停执行主线程,这意味着它还将阻止应用程序主页的重建,因此由于新的{{ 1}}状态。冻结应用程序结束后,它会立即进入新状态,这就是为什么您永远看不到加载页面的原因。
改为使用Load
,这将暂停执行其他await Future.delayed(Duration(seconds: 1));
函数,但不会阻塞主线程,因此您的MainPage会得到重建。