Flutter中消息传递
前言
在native开发中消息传递有多种手段,系统的广播,第三方的eventbus等,在flutter中会有哪些手段呢?本篇将会介绍
Flutter中的消息传递
InheritedWidget
InheritedWidget是Flutter中非常重要的一个功能型Widget,它可以高效的将数据在Widget树中向下传递、共享,这在一些需要在Widget树中共享数据的场景中非常方便, 我们经常通过这样的方式,通过BuildContext
,可以拿到Theme
和MediaQuery
InheritedWidget和React中的context功能类似,和逐级传递数据相比,它们能实现组件跨级传递数据。InheritedWidget的在Widget树中数据传递方向是从上到下的,这和Notification的传递方向正好相反。
在介绍StatefulWidget时,我们提到State对象有一个回调didChangeDependencies
,它会在“依赖”发生变化时被Flutter Framework调用。而这个“依赖”指的就是是否使用了父widget中InheritedWidget的数据,如果使用了,则代表有依赖,如果没有使用则代表没有依赖。这种机制可以使子组件在所依赖的主题、locale等发生变化时有机会来做一些事情 比如
1 | //得到状态栏的高度 |
使用InheritedWidget
主要涉及2部分工作量
- 创建一个继承自 InheritedWidget 的类,使用时将其插入 Widget 树
- 通过 BuildContext 对象提供的 inheritFromWidgetOfExactType 方法查找 Widget 树中最近的一个特定类型的 InheritedWidget 类的实例
共享数据类1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29class InheritedContext extends InheritedWidget {
//数据
final InheritedTestModel inheritedTestModel;
//点击+号的方法
final Function() increment;
//点击-号的方法
final Function() reduce;
InheritedContext({
Key key,
this.inheritedTestModel,
this.increment,
this.reduce,
Widget child,
}) : super(key: key, child: child);
static InheritedContext of(BuildContext context) {
return context.inheritFromWidgetOfExactType(InheritedContext);
}
//是否重建widget就取决于数据是否相同
bool updateShouldNotify(InheritedContext oldWidget) {
return inheritedTestModel != oldWidget.inheritedTestModel;
}
}
在widget中使用共享数据
1 | class CustomerWidgetB extends StatelessWidget { |
在树中从上向下传递
1 |
|
具体代码可以查看
常见错误
MediaQuery.of() called with a context that does not contain a MediaQuery
见ss https://stackoverflow.com/questions/50214338/flutter-error-mediaquery-of-called-with-a-context-that-does-not-contain-a-med
You need a MaterialApp
or a WidgetsApp
arround your widget. They provide the MediaQuery
. When you call .of(context)
Notification
notification 跟inheritedWidget恰恰相反,是从 子节点向父节点发送消息在Widget树中,每一个节点都可以分发通知,通知会沿着当前节点(context)向上传递,所有父节点都可以通过NotificationListener来监听通知,Flutter中称这种通知由子向父的传递为“通知冒泡”(Notification Bubbling)。Flutter中很多地方使用了通知,如可滚动(Scrollable) Widget中滑动时就会分发ScrollNotification,而Scrollbar正是通过监听ScrollNotification来确定滚动条位置的。
使用Notification
- 自定义通知
要继承自Notification类 - 分发通知
Notification有一个dispatch(context)
方法,它是用于分发通知的,我们说过context实际上就是操作Element的一个接口,它与Element树上的节点是对应的,通知会从context对应的Element节点向上冒泡。
1 | class CustomerNotification extends Notification { |
1 | class NotificationStudyState extends State<NotificationStudy> { |
注意:代码中注释的部分是不能正常工作的,因为这个context
是根Context,而NotificationListener是监听的子树,所以我们通过Builder
来构建RaisedButton,来获得按钮位置的context。
以上代码 参见 https://github.com/xsfelvis/learnflutter/tree/a2824a6d0db70fe3d4c92609cbd172ec7854ab3f/lib/demo6
事件总线
目前在已经有了一个eventbus插件
https://pub.flutter-io.cn/packages/event_bus#-readme-tab-
用法跟原生eventbus类似
引入
1
2
3import 'package:event_bus/event_bus.dart';
EventBus eventBus = new EventBus();监听事件
1
2
3eventBus.on().listen((event) {
print(event.runtimeType);
});发送事件
1
eventBus.fire(event);