【问题标题】:Flutter Bloc change state from different widgetFlutter Bloc 从不同的小部件更改状态
【发布时间】:2021-06-17 11:46:40
【问题描述】:

在我的应用主页上,我有一个列表视图,只要用户点击一个新页面,它就会重建。 我已经使用 flutter_bloc 插件实现了块模式,但我不知道如何从另一个小部件更改状态。

【问题讨论】:

    标签: flutter dart bloc


    【解决方案1】:

    使用颤振块更改状态时必须记住两件事:

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

    一个块的依赖注入

    案例 1. 您需要在一个路由中为小部件子树提供 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.bloccontext.repository 已弃用,取而代之的是 context.readcontext.watch

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

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

    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');
    }
    

    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 会自动处置带有实例化新路由上下文的 bloc 实例,但如果您使用 BlocProvider.value,则不会发生这种情况: 我已经花费了无数个小时来试图弄清楚如何防止自动处置。我使用的设置是在独立服务中创建块并由多个小部件使用。处理自动处理真是太痛苦了。谢谢分享。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 2021-03-19
      • 2020-03-10
      • 2021-11-29
      • 1970-01-01
      • 2020-04-17
      相关资源
      最近更新 更多