flutter Notification分析

前面提到InheritedWidget,它可以实现数据的冲上往下传递。那么从下往上传递呢?flutter 提供了 Notification 实现向上传递。
Notification中文意思是通知,与Android中的广播机制类似,在Flutter中Notification的功能是子节点状态变更,发送通知上报。
Notification的数据变更是通过Widgte树向上冒泡的,我们往往在下层Wdiget发送通知然后在上层处理通知。

//创建通知类
class MyNotification extends Notification {
  final String info;
  MyNotification(this.info);
}
//创建子Widget发送通知
class ChildWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
        onPressed: () => MyNotification("我是随机下面发送的数据:${Random().nextInt(1000)}").dispatch(context),
        child: Text("提交"),
      ),
    );
  }
}
//parentWidgte使用NotificationListener接收通知并显示
class ParentWidget extends StatefulWidget {
  @override
  _ParentWidgetState createState() => _ParentWidgetState();
}

class _ParentWidgetState extends State<ParentWidget> {
  String msg = "";

  onReceiveMessage(String message) {
    setState(() {
      msg =message;
    });
  }

  @override
  Widget build(BuildContext context) {
    return NotificationListener<MyNotification>(
      child: Column(
        children: [Text(msg), ChildWidget()],
      ),
      onNotification: (notification) {
        onReceiveMessage(notification.info);
        return true;
      },
    );
  }
}

源码

在这里插入图片描述
可以看到主要是两个类,。

  • dispatch()
  • visitAncestor(),

按照使用流程来分析,自定义一个Notification,调用dispatch(context)方法 来传递消息。dispatch(context)中调用了当前context的visitAncestorElements方法,该方法会从当前Element开始向上遍历父级元素;visitAncestorElements有一个遍历回调参数,在遍历过程中对遍历到的父级元素都会执行该回调。遍历的终止条件是:已经遍历到根Element或某个遍历回调返回false。源码中传给visitAncestorElements方法的遍历回调为visitAncestor方法,

//遍历回调,会对每一个父级Element执行此回调
bool visitAncestor(Element element) {
  //判断当前element对应的Widget是否是NotificationListener。

  //由于NotificationListener是继承自StatelessWidget,
  //故先判断是否是StatelessElement
  if (element is StatelessElement) {
    //是StatelessElement,则获取element对应的Widget,判断
    //是否是NotificationListener 。
    final StatelessWidget widget = element.widget;
    if (widget is NotificationListener<Notification>) {
      //是NotificationListener,则调用该NotificationListener的_dispatch方法
      if (widget._dispatch(this, element)) 
        return false;
    }
  }
  return true;
}

visitAncestor会判断每一个遍历到的父级Widget是否是NotificationListener,如果不是,则返回true继续向上遍历,如果是,则调用NotificationListener的_dispatch方法,我们看看_dispatch方法的源码

 bool _dispatch(Notification notification, Element element) {
    // 如果通知监听器不为空,并且当前通知类型是该NotificationListener
    // 监听的通知类型,则调用当前NotificationListener的onNotification
    if (onNotification != null && notification is T) {
      final bool result = onNotification(notification);
      // 返回值决定是否继续向上遍历
      return result == true; 
    }
    return false;
  }

我们可以看到NotificationListener的onNotification回调最终是在_dispatch方法中执行的,然后会根据返回值来确定是否继续向上冒泡。
1.Context上也提供了遍历Element树的方法。
2.我们可以通过Element.widget得到element节点对应的widget;我们已经反复讲过Widget和Element的对应关系,读者通过这些源码来加深理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值