首页 > 解决方案 > 为什么未显式设置 bloc 时从未调用 BlocBuilder

问题描述

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

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

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

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

下面的代码不起作用。该事件被调度,但构建器永远不会被调用。

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>(
          builder: (context, count) => CountView(count),
        ),
        floatingActionButton: AddButton(
            action: () => BlocProvider.of<CounterBloc>(context)
                .add(CounterEvent.increment)),
      ),
    );
  }
}

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

标签: flutterblocflutter-bloc

解决方案


我相信CounterEvent.incrementfrom not working 代码段不会被调度,而是会抛出错误BlocProvider.of() called with a context ...,因为您context在提供bloc.

此代码有效,因为它是contextBlocProvider 之后的新代码

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()和使用bloc通过 BlocProvider 提供的实例。

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

推荐阅读