繁体   English   中英

Flutter 从不同的小部件更改 state

[英]Flutter Bloc change state from different widget

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

使用 flutter 块更改 state 时必须记住两件事:

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

一个块的依赖注入

案例 1. 您需要在一个路由中为小部件子树提供块。


要为子树中的多个小部件提供一个块的单个实例,请使用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。您需要从另一条路线(到另一个上下文)为小部件提供块。


BlocProvider自动处理带有实例化新路由上下文的 bloc 实例,但如果您使用BlocProvider.value ,则不会发生这种情况:

BlocProvider.value(
  value: BlocProvider.of<BlocA>(context),
  child: ScreenA(),
);

重要提示: BlocProvider.value只能用于将现有实例提供给新的子树,不要用它创建 Bloc 实例

与您的 bloc 实例交互

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

context.select允许基于块 state 的一部分更新 UI:

    final name = context.select((UserBloc bloc) => bloc.state.user.name);

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

访问集团的 state

如果您需要重建由于块值更改而导致的小部件,请使用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');
}

或使用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()),
    ...
  )
}

您可以将BlocProvider到一个公共的 ansestor 中,例如作为MaterialApp小部件的父级,或者您可以将 bloc 传递给您的新页面,如下所示:

BlocProvider.value(
  value: BlocProvider.of<BlocA>(context),
  child: ScreenB(),
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM