Flutter Bloc 没有重建状态
Flutter Bloc is not rebuilding state
我已经使用 flutter_bloc 包实现了这个简单的 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 {}
我的 UI 看起来像这样:
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 不会重建加载状态。输出如下:
I/flutter(1955 年):屈服状态:'Load'
的实例
I/flutter(1955 年):屈服状态:'Init'
的实例
I/flutter(1955 年):构建状态:'Init'
的实例
因为你用的是await sleep(Duration(seconds: 1));
(await
语句在这里没有用,是同步函数)
sleep
函数会暂停主线程的执行,这意味着它还会阻止重建应用程序的主页,因此它没有机会重建,因为新的Load
状态。冻结应用程序结束后,它会立即进入新状态,这就是为什么您永远不会看到加载页面的原因。
改用 await Future.delayed(Duration(seconds: 1));
,这会暂停 _mapEventToState
函数其余部分的执行,但不会阻塞主线程,因此您的 MainPage 会得到重建。
我已经使用 flutter_bloc 包实现了这个简单的 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 {}
我的 UI 看起来像这样:
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 不会重建加载状态。输出如下:
I/flutter(1955 年):屈服状态:'Load'
的实例I/flutter(1955 年):屈服状态:'Init'
的实例I/flutter(1955 年):构建状态:'Init'
的实例因为你用的是await sleep(Duration(seconds: 1));
(await
语句在这里没有用,是同步函数)
sleep
函数会暂停主线程的执行,这意味着它还会阻止重建应用程序的主页,因此它没有机会重建,因为新的Load
状态。冻结应用程序结束后,它会立即进入新状态,这就是为什么您永远不会看到加载页面的原因。
改用 await Future.delayed(Duration(seconds: 1));
,这会暂停 _mapEventToState
函数其余部分的执行,但不会阻塞主线程,因此您的 MainPage 会得到重建。