当前位置:网站首页>BlocProvider 为什么感觉和 Provider 很相似?
BlocProvider 为什么感觉和 Provider 很相似?
2022-07-01 21:38:00 【InfoQ】
前言
上一篇
不到 40 行代码手撸一个 BlocProvider
,我们只用了不到40行代码手撸了一个
SimpleBlocProvider
,用起来感觉也还可以,这就是 Bloc 的优势之一,你可以基于
Bloc
这种模式自己做扩展,形成自己的状态管理组件。我们这一篇来看看官方
flutter_bloc
插件提供的
BlocProvider
怎么样。
Provider 的模仿者?
我们先来看
BlocProvider
实现的计数器示例代码:
class BlocCounterWrapper extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: BlocCounterPage(),
);
}
}
class BlocCounterPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Bloc 计数器'),
),
body: Center(
child: BlocBuilder<CounterCubit, int>(
builder: (context, count) => Text(
'$count',
style: TextStyle(
fontSize: 32,
color: Colors.blue,
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<CounterCubit>().increment();
},
tooltip: '点击增加',
child: Icon(Icons.add),
),
);
}
}
这代码是不是十分熟悉?如果回顾我们之前的
Provider
状态管理,感觉是十分相似啊!比如:
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterCubit(),
child: BlocCounterPage(),
);
}
在
Provider
里实现就是下面这样。
Widget build(BuildContext context) {
return Provider(
create: (_) => CounterCubit(),
child: BlocCounterPage(),
);
}
而在
FloatingActionButton
里的
context.read
用法也和
Provider
里的一样。所以,如果要从
Provider
迁移到 Bloc 也是十分简单的。实际从源码逐层向上,你会发现里面就有 provider 的代码。
library flutter_bloc;
export 'package:bloc/bloc.dart';
export 'package:provider/provider.dart'
show ProviderNotFoundException, ReadContext, SelectContext, WatchContext;
而从
Provider
和
bloc
的GitHub源码贡献者中我们也发现
Provider
的代码贡献者Felix Angelov 就是 bloc 代码的发起者。。


所以这就不奇怪 Bloc 中使用 Provider 了。
与 Provider 的异同
BlocProvider
和
Provider
一样,通过组件树为子组件提供状态数据。也就是我们可以像使用
Provider
一样使用
BlocProvider
,比如使用已有的状态对象时的哟用法和
Provider
一样使用
value
参数赋值:
final counter = CounterCubit();
//...
BlocProvider.value(
value: counter,
child: SomeWidget(),
);
在比如可以在子组件中使用
context.read
和
context.watch
。以及使用 select 方法监听状态数据的部分变化。
final isPositive = context.select((CounterBloc b) => b.state >= 0);
还有
MultiBlocProvider
来向子组件树传递多个Bloc状态对象。
MultiBlocProvider(
providers: [
BlocProvider<BlocA>(
create: (BuildContext context) => BlocA(),
),
BlocProvider<BlocB>(
create: (BuildContext context) => BlocB(),
),
BlocProvider<BlocC>(
create: (BuildContext context) => BlocC(),
),
],
child: ChildA(),
)
可以说,如果之前你用
Provider
状态管理的话,可以无缝迁移到
BlocProvider
。当然,状态对象类还是需要改一下的。这也是
BlocProvider
和
Provider
的区别。比如状态对象不需要实现
ChangeNotifier
接口,在状态数据改变的时候也无需调用
notifyListeners
来通知刷新。实际我们从
BlocProvider
的源码扒出了一段监听状态对象实现的方法,这里其实也是使用我们在
SimpleBlocProvider
中使用的
Stream.listen
方法来实现的。
static VoidCallback _startListening(
InheritedContext<BlocBase?> e,
BlocBase value,
) {
final subscription = value.stream.listen(
(dynamic _) => e.markNeedsNotifyDependents(),
);
return subscription.cancel;
}
而其他部分的代码基本就是复用
Provider
的代码。所以
BlocProvider
可以看成是使用了
Stream.listen
监听状态数据的方式替换
ChangeNotifer
的
Provider
的变种。因此,如果想从
Provider
切换到
BlocProvider
,可以大胆地切换,代码修改工作量很低。而且无需在状态对象里反复调用
notifyListeners
来通知界面刷新了。
总结
本篇介绍了
BlocProvider
的使用,从写法上来看,感觉不到太多的优势,个人估计这是作者想让
Provider
的用户可以直接切换到
BlocProvider
才提供了这么一个
Provider
的替代品。不过,这只是冰山一脚,实际上,
flutter_bloc
还提供了很多其他的选择,我们接下来会一一介绍。

边栏推荐
猜你喜欢
随机推荐
Oracle deadlock test
基于三维GIS的不动产管理应用
运放-滞回(迟滞)比较器全流程实战计算
杰理之蓝牙耳机品控和生产技巧【篇】
Customize the insertion of page labels and realize the initial search of similar address books
Penetration tools - trustedsec's penetration testing framework (PTF)
旁路由设置的正确方式
“丝路正青春 风采看福建”在闽外籍青年短视频大赛火热征集作品中
2022安全员-B证考试练习题模拟考试平台操作
leetcode刷题:栈与队列06(前 K 个高频元素)
【Opencv450】HOG+SVM 与Hog+cascade进行行人检测
升级版手机检测微信工具小程序源码-支持多种流量主模式
分离字符串中的字母和数字并使得字母在前数组在后
An operation tool used by we media professionals who earn 1w+ a month
杰理之蓝牙耳机品控和生产技巧【篇】
能升职加薪?PMP证书含金量浅析
deb文件安装
leetcode刷题:二叉树03(二叉树的后序遍历)
Pytest collection (2) - pytest operation mode
leetcode刷题:栈与队列05(逆波兰表达式求值)