Flutter Bloc 从不同的小部件更改状态
Flutter Bloc change state from different widget
在我的应用程序主页上,我有一个列表视图,只要用户单击新页面就会重建。
我已经使用 flutter_bloc 插件实现了块模式,但我不知道如何从另一个小部件更改状态。
您可以将 BlocProvider
放置到一个共同的祖先,例如 MaterialApp
小部件的父级,或者您可以像这样将 bloc 传递到您的新页面:
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenB(),
);
使用 flutter bloc 改变状态需要记住两点:
- 一个区块的依赖注入 (DI)。
- 与您的 bloc 实例互动。
一个区块的依赖注入
情况1.您需要在一个路由中为widget子树提供bloc。
要向子树中的多个小部件提供 bloc 的单个实例,您可以使用 BlocProvider
小部件。它创建 bloc 实例,在需要时自动处理它并通过 BlocProvider.of<T>(context)
向其子级提供 bloc,其中 T
是您的 bloc 的名称:
BlocProvider(
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
请记住,默认情况下它是用 属性 lazy: true
创建的,这意味着 create: (BuildContext context) => BlocA(),
将在调用 BlocProvider.of<T>(context)
之后执行。如果您不想要它 - 提前设置 lazy: false
。
情况 2. 您需要从另一条路线(到另一条上下文)向小部件提供 bloc。
BlocProvider
自动处理带有实例化新路由上下文的 bloc 实例,但如果您使用 BlocProvider.value
:
则不会发生这种情况
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenA(),
);
重要提示:BlocProvider.value
只能用于为新子树提供现有实例,不要用它创建 Bloc 实例
与您的 bloc 实例互动
从 bloc v6.1.0
开始,context.bloc
和 context.repository
已弃用,取而代之的是 context.read
和 context.watch
。
context.select
允许根据 bloc 状态的一部分更新 UI:
final name = context.select((UserBloc bloc) => bloc.state.user.name);
context.read
使用 BuildContext 访问一个 bloc 并且不会导致重建。
context.watch
从与其类型最近的祖先提供者获取值并订阅该提供者。
访问区块状态
如果您需要一个小部件重建由于 bloc 值更改使用 context.watch
或 BlocBuilder
:
// Using context.watch at the root of the build method will result in the entire widget being rebuilt when the bloc state changes.
@override
Widget build(BuildContext context) {
final state = context.watch<MyBloc>().state;
return Text('$state');
}
或 BlocBuilder
:
// If the entire widget does not need to be rebuilt, either use BlocBuilder to wrap the parts that should rebuild
@override
Widget build(BuildContext context) {
return BlocBuilder<MyBloc, MyState>(
builder: (context, state) => Text('$state'),
);
}
访问区块以便添加事件
使用context.read:
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => context.read<MyBloc>().add(MyEvent()),
...
)
}
在我的应用程序主页上,我有一个列表视图,只要用户单击新页面就会重建。 我已经使用 flutter_bloc 插件实现了块模式,但我不知道如何从另一个小部件更改状态。
您可以将 BlocProvider
放置到一个共同的祖先,例如 MaterialApp
小部件的父级,或者您可以像这样将 bloc 传递到您的新页面:
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenB(),
);
使用 flutter bloc 改变状态需要记住两点:
- 一个区块的依赖注入 (DI)。
- 与您的 bloc 实例互动。
一个区块的依赖注入
情况1.您需要在一个路由中为widget子树提供bloc。
要向子树中的多个小部件提供 bloc 的单个实例,您可以使用 BlocProvider
小部件。它创建 bloc 实例,在需要时自动处理它并通过 BlocProvider.of<T>(context)
向其子级提供 bloc,其中 T
是您的 bloc 的名称:
BlocProvider(
create: (BuildContext context) => BlocA(),
child: ChildA(),
);
请记住,默认情况下它是用 属性 lazy: true
创建的,这意味着 create: (BuildContext context) => BlocA(),
将在调用 BlocProvider.of<T>(context)
之后执行。如果您不想要它 - 提前设置 lazy: false
。
情况 2. 您需要从另一条路线(到另一条上下文)向小部件提供 bloc。
BlocProvider
自动处理带有实例化新路由上下文的 bloc 实例,但如果您使用 BlocProvider.value
:
BlocProvider.value(
value: BlocProvider.of<BlocA>(context),
child: ScreenA(),
);
重要提示:BlocProvider.value
只能用于为新子树提供现有实例,不要用它创建 Bloc 实例
与您的 bloc 实例互动
从 bloc v6.1.0
开始,context.bloc
和 context.repository
已弃用,取而代之的是 context.read
和 context.watch
。
context.select
允许根据 bloc 状态的一部分更新 UI:
final name = context.select((UserBloc bloc) => bloc.state.user.name);
context.read
使用 BuildContext 访问一个 bloc 并且不会导致重建。
context.watch
从与其类型最近的祖先提供者获取值并订阅该提供者。
访问区块状态
如果您需要一个小部件重建由于 bloc 值更改使用 context.watch
或 BlocBuilder
:
// Using context.watch at the root of the build method will result in the entire widget being rebuilt when the bloc state changes.
@override
Widget build(BuildContext context) {
final state = context.watch<MyBloc>().state;
return Text('$state');
}
或 BlocBuilder
:
// If the entire widget does not need to be rebuilt, either use BlocBuilder to wrap the parts that should rebuild
@override
Widget build(BuildContext context) {
return BlocBuilder<MyBloc, MyState>(
builder: (context, state) => Text('$state'),
);
}
访问区块以便添加事件
使用context.read:
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => context.read<MyBloc>().add(MyEvent()),
...
)
}