为什么在未明确设置bloc的情况下从未调用BlocBuilder

时间:2020-04-24 17:06:49

标签: flutter bloc flutter-bloc

这是Flutter计数器应用程序的示例。我用这样的Bloc实例化Counter:

./node_modules/my_module/data

下面的代码可以正常工作。分派事件并调用“ builder”方法。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Counter(CounterBloc()),
    );
  }
}

下面的代码不起作用。该事件已调度,但从未调用过构建器。

class Counter extends StatelessWidget {
  final Bloc bloc;

  const Counter(this.bloc, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterBloc>(
      create: (context) => bloc,
      child: CounterPage(),
    );
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocBuilder<CounterBloc, int>(
        builder: (context, count) => CountView(count),
      ),
      floatingActionButton: AddButton(
          action: () => BlocProvider.of<CounterBloc>(context)
              .add(CounterEvent.increment)),
    );
  }
}

我发现可以在“ BlocBuilder”上设置属性“ bloc”,但是我希望这不是必需的。 为什么行为不同?

1 个答案:

答案 0 :(得分:0)

我认为,CounterEvent.increment不会正常工作,不会被分派,而是会引发错误BlocProvider.of() called with a context ...,因为您在提供context的地方使用了相同的bloc

此代码之所以有效,是因为它是BlocProvider之后的新context

class Counter extends StatelessWidget {
  final Bloc bloc;

  const Counter(this.bloc, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterBloc>(
      create: (context) => bloc,
      child: Builder(
        builder: (context) => Scaffold(
          body: BlocBuilder<CounterBloc, int>(
            builder: (context, count) => CountView(count),
          ),
          floatingActionButton: AddButton(
            action: () => BlocProvider.of<CounterBloc>(context)
                .add(CounterEvent.increment),
          ),
        ),
      ),
    );
  }
}

该代码之所以有效,是因为我们显式使用了构造函数中的bloc实例,而不是调用BlocProvider.of()并使用了BlocProvider提供的bloc实例。

class Counter extends StatelessWidget {
  final Bloc bloc;

  const Counter(this.bloc, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterBloc>(
      create: (context) => bloc,
      child: Scaffold(
        body: BlocBuilder<CounterBloc, int>(
          bloc: bloc,
          builder: (context, count) => CountView(count),
        ),
        floatingActionButton: AddButton(
          action: () => bloc.add(CounterEvent.increment),
        ),
      ),
    );
  }
}

以上两种代码片段都可以使用,但这并不是“正确”的方法。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Counter(
        CounterBloc(), // <=() You need a work around to dispose this instance
      ),
    );
  }
}