Notification是Flutter重要的状态管理机制之一,它可以很方便的显现子widget通知其父widget自身的某些状态发生了改变,它和另一种状态管理部件 InheritedWidget有些类似,InheritedWidget是父widget通知子widget,Notification是子widget通知父widget。
下面是Notification的用法:
NotificationListener<ScrollEndNotification>(
onNotification: (notification){
print('onScrollEnd');
return false;
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text("$index"),);
}
),
);
以上代码实现的是监听滚动部件的滚动结束状态,但是当我们既想监听滚动结束状态又想监听滚动开始状态怎么办?有两种办法
第一种:
NotificationListener<ScrollStartNotification>(
onNotification: (notification) {
print('onScrollStart');
return false;
},
child: NotificationListener<ScrollEndNotification>(
onNotification: (notification) {
print('onScrollEnd');
return false;
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
title: Text("$index"),
);
}),
));
第二种:
NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollStartNotification) {
print('onScrollStart');
} else if (notification is ScrollEndNotification) {
print('onScrollEnd');
}
return false;
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
title: Text("$index"),
);
}));
第一种写法一旦要监听的Notification增多时就会造成嵌套地狱;
第二种写法的前提是多个 Notification是同一个父类的派生类,当然所有Notification都是Notification
这个类的派生类,我们可以通过直接监听Notification来实现监听多种变化的需求,但是这样父widget就会收到子widget发出的所有事件,不论这些状态父widget是否关注,出于性能和代码健壮性考虑这都是不可取的。
事实上想要解决这个需求也很简单,只需要解决第一种写法可能导致的嵌套地狱就可以了,Notification
本质上也是个widget,而widget的嵌套地狱是很好解决的,只需要使用到Dart的类扩展extension
就可以了
extension WidgetExt on Widget {
NotificationListener<T> intoNotification<T extends Notification>({Key key, NotificationListenerCallback<T> onNotification}) {
return NotificationListener<T>(key: key, onNotification: onNotification, child: this);
}
}
我们还可以通过extension
来解决很多由widget嵌套导致的代码结构不合理的问题,我在项目中就经常用到对Container
、Center
、GestureDetector
等等的扩展。