Notification
NotificationListener也是冒泡传递,和触摸Listener不同的是:NotificationListener可以通过onNotification阻止继续冒泡,而Listener不行。
通知使用流程
通知类,每个节点都可以发送通知Notification,每个节点也都可以接收通知。通知通过冒泡逐级往父类查找对于泛型的NotificationListener
监听。
下面我们先制定一个通知类继承Notification
, 走一遍通知流程:
自定义通知类
1 | import 'package:flutter/material.dart'; |
发送通知
通过通知实例,调用dispatch方法,dispatch方法默认在抽象类Notification实现
1 | RZNotification notification = RZNotification(count: 5); |
监听通知
1 | NotificationListener<RZNotification>( |
NotificationListener
监听类只有两个成员child和onNotification,一个私有方法(_dispatch
),一个build方法,build方法直接返回传入child。
_dispatch
通知类通过element树查找所有通知监听类NotificationListener
,调用监听类的_dispatch,并传入通知类实例。_dispatch
方法校验是否属于自己监听的泛型类,如果是并且onNotification方法返回为true。
接收Notification
对应泛型子类的通知,对于泛型子类通过dispatch(BuildContent? target)
方法——通过element树层层往上级查找,找到对应泛型的Listener,即调用onNotification
回调。
再看Notification
dispatch(BuildContent? target)
Notification
类为抽象类,子类直接调用dispatch
方法,通过传入BuildContent
的visitAncestorElements
查找,并传入查找逻辑(visitor)
visitAncestorElements
是BuildContent实例方法:
1 | @override |
个人理解是传入一个访问逻辑,visitAncestorElements
逐级往上查找父类——do循环,如果父类不为空,将父类传入访问逻辑中,如果访问逻辑返回true就继续查找改父类的父类,如果返回false,就停止查找。
visitAncestor
访问逻辑visitAncestor,并不知道是那个子类调用的dispatch方法,所以先查找widget is NotificationListener<Notification>
,是的话就调用NotificationListener的_dispatch方法,并传入调用者,NotificationListener都知道自己监听的泛型类是什么,如果是调用者是自己监听的类,即调用onNotification
回调。
1 | @protected |
总结
通过NotificationListener和Notification配合,我们清晰知道了通知发送和接收的逻辑。通知这种方式的通信也有它的局限性,监听者只能监听其子widget发送的通知。所以我们也需要根据应用场景实际情况选择性去使用。
并且熟悉了Context和Element关系:
- Context遍历Element树的方法
- 可以通过Element.widget得到element节点对应的widget