flutter - 为什么未显式设置 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”,但我希望这不是必需的。为什么行为上的差异?
解决方案
我相信CounterEvent.increment
from not working 代码段不会被调度,而是会抛出错误BlocProvider.of() called with a context ...
,因为您context
在提供bloc
.
此代码有效,因为它是context
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: 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
),
);
}
}
推荐阅读
- javascript - 帮助您显示答案的按钮
- apache-spark - 如何在火花结构化流式读取流中倒带 Kafka 偏移
- python - 具有多个队列的 Python 分布式任务
- html - 在 Django 中将模型插入表单时打开标签问题
- ios - 迭代 Swift 扩展中的可用类?
- ios - Firebase Root上的IndexOn以快速查询整个数据库3
- ruby-on-rails - 扩展 Rails 需要大量 Nginx 实例
- javascript - Node.js 是 JavaScript 运行时环境还是 EcmaScript 环境?
- python - 在 sklearn 中绘制类权重的验证曲线
- jasper-reports - 基于变量对 JasperReport 进行分组