一,概述

  Notification是Flutter中一个重要的机制,在Widget树中,每一个节点都可以分发通知,通知会沿着当前节点(context)向上传递,所有父节点都可以通过NotificationListener来监听通知,Flutter中称这种通知由子向父的传递为“通知冒泡”(Notification Bubbling),这个和用户触摸事件冒泡是相似的,但有一点不同:通知冒泡可以中止,但用户触摸事件不行。

  Flutter中很多地方使用了通知,如可滚动(Scrollable) Widget中滑动时就会分发ScrollNotification,而Scrollbar正是通过监听ScrollNotification来确定滚动条位置的。除了ScrollNotification,Flutter中还有SizeChangedLayoutNotification、KeepAliveNotification 、LayoutChangedNotification等。下面是一个监听Scrollable Widget滚动通知的例子:

NotificationListener(
onNotification: (notification){
//print(notification);
switch (notification.runtimeType){
case ScrollStartNotification: print("开始滚动"); break;
case ScrollUpdateNotification: print("正在滚动"); break;
case ScrollEndNotification: print("滚动停止"); break;
case OverscrollNotification: print("滚动到边界"); break;
}
},
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text("$index"),);
}
),
);

上例中的滚动通知如ScrollStartNotification、ScrollUpdateNotification等都是继承自ScrollNotification类,不同类型的通知子类会包含不同的信息,比如ScrollUpdateNotification有一个scrollDelta属性,它记录了移动的位移,其它通知属性读者可以自己查看SDK文档。

二,自定义通知

除了Flutter内部通知,我们也可以自定义通知,下面我们看看如何实现自定义通知:

  • 定义一个通知类,要继承自Notification类;

    class TestNotification extends Notification {
    TestNotification({
    @required this.count,
    });
    final int count;
    }
  • 子节点发送通知。

    new RaisedButton(
    textColor: Colors.black,
    child: new Center(
    child: new Text('点击传递随机数给上层Widget'),
    ),
    onPressed: () {
    new TestNotification(count: new Random().nextInt(100)).dispatch(key.currentContext);
    })
  • 父节点使用NotificationListener进行监听子节点发出的通知,并作出响应
    new NotificationListener(
    onNotification: (TestNotification n) {
    scaffoldStateKey.currentState.showSnackBar(new SnackBar(content: new Text('随机数:${n.count}')));
    return true;
    },
    child: new TestAPage(
    key: key,
    ))

Notification有一个dispatch(context)方法,它是用于分发通知的,我们说过context实际上就是操作Element的一个接口,它与Element树上的节点是对应的,通知会从context对应的Element节点向上冒泡。

  • 示例
    下面我们看一个完整的例子:

    class NotificationRoute extends StatefulWidget {
    @override
    NotificationRouteState createState() {
    return new NotificationRouteState();
    }
    } class NotificationRouteState extends State<NotificationRoute> {
    String _msg="";
    @override
    Widget build(BuildContext context) {
    //监听通知
    return NotificationListener<MyNotification>(
    onNotification: (notification) {
    setState(() {
    _msg+=notification.msg+" ";
    });
    },
    child: Center(
    child: Column(
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
    // RaisedButton(
    // onPressed: () => MyNotification("Hi").dispatch(context),
    // child: Text("Send Notification"),
    // ),
    Builder(
    builder: (context) {
    return RaisedButton(
    //按钮点击时分发通知
    onPressed: () => MyNotification("Hi").dispatch(context),
    child: Text("Send Notification"),
    );
    },
    ),
    Text(_msg)
    ],
    ),
    ),
    );
    }
    } class MyNotification extends Notification {
    MyNotification(this.msg);
    final String msg;
    }

    上面代码中,我们每点一次按钮就会分发一个MyNotification类型的通知,我们在Widget根上监听通知,收到通知后我们将通知通过Text显示在屏幕上。

    注意:代码中注释的部分是不能正常工作的,因为这个context是根Context,而NotificationListener是监听的子树,所以我们通过Builder来构建RaisedButton,来获得按钮位置的context。

    运行效果如下:

最新文章

  1. 利用snowfall.jquery.js实现爱心满屏飞
  2. Func与Action
  3. 伪随机数(线性同余法)C语言
  4. sqlservr (708) 打开日志文件 C:\Windows\system32\LogFiles\Sum\Api.log 时出现错误 -1032 (0xfffffbf8)
  5. SPI线协议详解
  6. 关键路径 SDUTOJ 2498
  7. POJ1745Divisibility(01背包思想)
  8. Android系统Recovery工作原理之使用update.zip升级过程分析(一)
  9. Mysqldb连接Mysql数据库(转)
  10. MongoDB学习笔记05
  11. SE 2014年4月18日
  12. 转让malloc()该功能后,发生了什么事内核?附malloc()和free()实现源
  13. Allegro pcb -等长设计
  14. Mac实用操作技巧(三)
  15. c/c++ linux 进程间通信系列3,使用socketpair,pipe
  16. robot framework---时间控件取值
  17. 【Codeforces Round 1117】Educational Round 60
  18. 归并排序O(nlogn)
  19. [转载]win7x64下的redis安装与使用
  20. javascript 完美解决对联广告

热门文章

  1. Dataphin的代码自动化能力如何助力商业决策
  2. Rabin算法
  3. 【靶场练习_sqli-labs】SQLi-LABS Page-3 (Stacked Injections)
  4. centos挂载移动硬盘ntfs-3g
  5. error C2065: “SHELLEXECUTEINFO”: 未声明的标识符
  6. python中列表元素连接方法join用法实例
  7. Markdown ![...](...) --&gt; &lt;img ... /&gt;
  8. vscode 配置 golang开发环境
  9. Can&#39;t connect to local MySQL server through socket &#39;/opt/lampp/var/mysql/mysql.sock&#39; (2)
  10. [Leetcode] 176.第二高薪水