Flutter Bloc 从不同的小部件更改状态

Nis*_*n S 3 dart flutter bloc

在我的应用程序主页上,我有一个列表视图,每当用户单击新页面时都会重建该视图。我已经使用 flutter_bloc 插件实现了块模式,但我不知道如何更改另一个小部件的状态。

Sim*_*Sot 13

使用 flutter bloc 改变状态时必须记住两件事:

  • 块的依赖注入 (DI)。
  • 与您的块实例交互。

块的依赖注入

情况 1. 您需要在一个路由内向小部件子树提供块。


要向子树中的多个小部件提供块的单个实例,您可以使用BlocProvider小部件。它创建 bloc 实例,在需要时自动处理它,并通过 向其子级提供 bloc BlocProvider.of<T>(context),其中T是您的 bloc 的名称:

BlocProvider(
  create: (BuildContext context) => BlocA(),
  child: ChildA(),
);
Run Code Online (Sandbox Code Playgroud)

请记住,默认情况下它是使用 property 创建的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(),
);
Run Code Online (Sandbox Code Playgroud)

重要提示:BlocProvider.value仅应用于向新子树提供现有实例,不要用它创建 Bloc 实例

与您的块实例交互

bloc v6.1.0 context.bloc和开始context.repository已被弃用,取而代之的是context.readcontext.watch

context.select允许根据块状态的一部分更新 UI:

    final name = context.select((UserBloc bloc) => bloc.state.user.name);
Run Code Online (Sandbox Code Playgroud)

context.read使用 BuildContext 访问块并且不会导致重建。 context.watch从其类型的最近祖先提供者获取值并订阅该提供者。

访问该集团的状态

如果您需要由于块值更改而重建小部件,请使用context.watchBlocBuilder

// 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');
}
Run Code Online (Sandbox Code Playgroud)

或与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'),
  );
}
Run Code Online (Sandbox Code Playgroud)

访问该块以便添加事件

使用 context.read:

@override
Widget build(BuildContext context) {
  return ElevatedButton(
    onPressed: () => context.read<MyBloc>().add(MyEvent()),
    ...
  )
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该出现在他们的第一个教程中。**BlocProvider 会自动处理实例化新路由上下文的 bloc 实例,但如果您使用 BlocProvider.value,则不会发生这种情况:** 我已经花费了无数时间试图弄清楚如何防止自动处理。我使用的设置是在独立服务中创建块并由多个小部件使用。处理自动处置真是太痛苦了。感谢你的分享。 (4认同)