Flutter入门系列-EventBus事件总线

一、EventBus 事件总线

在App中,我们经常会需要广播机制,用以跨页面事件通知,比如一个需要登录的App中,页面会关注用户登录或者注销事件,来进行一些状态更新。这时候,一个事件总线便会非常有用,事件总线通常实现了订阅模式,订阅者模式包含了发布者和订阅者两种角色,可以通过事件总线来触发事件和监听事件, 下面我们实现一个简单的全局事件总线,使用单例模式。 

二、代码实现

//event_bus.dart
//订阅者回调签名
typedef void EventCallback(arg);

class EventBus {
  //私有构造函数
  EventBus._internal();

  //保持单例
  static EventBus _singleton = EventBus._internal();

  //工厂构造函数
  factory EventBus() => _singleton;

  //保存事件订阅者队列,key: 事件名成 value:对应的事件订阅者队列
  final _emap = Map<Object, List<EventCallback>>();

  //添加订阅者
  void on(eventName, EventCallback f) {
    _emap[eventName] ??= <EventCallback>[];
    _emap[eventName].add(f);
  }

  //移除订阅者
  void off(eventName, [EventCallback f]) {
    var list = _emap[eventName];
    if (eventName == null || list == null) {
      return;
    }
    if (f == null){
       _emap[eventName] = null;
    } else {
       list.remove(f);
    }
  }

  //触发事件,事件触发后该事件所有订阅者会被调用
  void emit(eventName, [arg]) {
    var list = _emap[eventName];
    if (list ==null) return;
    int len = list.length-1;
    //反向遍历,防止订阅者在回调中移除自身带来的下标错位
    for (var i=len; i>-1; --i){
        list[i](arg);
    }
  }
}

//定义一个top-level(全局)变量,页面A中订阅者会被调用
var bus = EventBus();
import 'package:flutter/material.dart';
import 'event_bus.dart';

class EventBusAPage extends StatefulWidget {
  const EventBusAPage({Key key}) : super(key: key);

  @override
  _EventBusAPageState createState() => _EventBusAPageState();
}

class _EventBusAPageState extends State<EventBusAPage> {

  var data ='';

  @override
  void initState() {
    super.initState();
    bus.on("doAction", (arg){
         print('doAction $arg');
         data = arg;
         setState(() {

         });
    });
  }

  @override
  void dispose() {
    super.dispose();
    bus.off('doAction');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('EventBusPageA'),
      ),
      body: Container(
        child: Column(
          children: [
            MaterialButton(
              onPressed: () {
                  Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){
                       return EventBusBPage();
                  }));
              },
              child: Text('跳转到PageB'),
            ),
            Text(data, style: TextStyle(color: Colors.black, fontSize: 16),
            )
          ],
        ),
      ),
    );
  }
}


class EventBusBPage extends StatefulWidget {
  const EventBusBPage({Key key}) : super(key: key);

  @override
  _EventBusBPageState createState() => _EventBusBPageState();
}

class _EventBusBPageState extends State<EventBusBPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('EventBusPageB'),
      ),
      body: Container(
        child: Column(
          children: [
            MaterialButton(
              onPressed:()=> bus.emit('doAction', "hello PageA from PageB"),
              child: Text('更新页面A的数据'),
            ),
          ],
        ),
      ),
    );
  }
}

效果如下: 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值