Flutter之全局事件(消息)总线EventBus

Flutter是Google(全球顶级互联网科技公司)的生的,后台够硬,毫无疑问Flutter即将或已经成为跨平台开发的主流,Flutter野心很大,不仅冲击着原生开发,而且很有可能会烧到Web前端。作为移动端开发者的你,如果不关注Flutter的话,实在说不过去啦!

在APP中,我们经常会需要一个广播机制,用以跨页面事件通知。比如从第一个页面跳转到第二个页面,用户在第二个页面操作的动作行为要及时反馈到第一个页面中(如刷新页面中的数据)。这种场景,一个事件总线便会非常有用,事件总线通常实现了订阅者模式,订阅者模式包含发布者和订阅者两种角色,可以通过事件总线来触发事件和监听事件,本文介绍如何在Flutter中使用EventBus,实现类似以上的场景。

一、效果图

第一个界面初始化状态
在这里插入图片描述
第二个界面使用按钮点击发起一个EventBus事件
在这里插入图片描述
第一个界面展示了第二个界面发送的数据(即更新了UI)
在这里插入图片描述
2、Flutter中集成EventBus

在pubspec.yaml文件中添加event_bus,当前版本1.1.0:

event_bus:  ^1.1.0

2、引入EventBus

import 'package:event_bus/event_bus.dart';

3、创建EventBus实例

EventBus eventBus = new EventBus();

YDCEventBusManage.dart全部代码

import 'package:event_bus/event_bus.dart';
EventBus eventBus = new EventBus();

4、定义event, 任意一个Dart class都可以作为一个event

class EventParam{
   String id;
   String name;
   EventParam(this.id,this.name);
   String get getName => this.name;
   String get getId=>this.id;
}

4、在第一个页面中注册监听

EventBus是通过Dart Streams来实现的,那么我们可以通过对Dart Stream的控制,来实现对EventBus的控制。
在这里插入图片描述
监听eventBus中所有的事件。

eventBus.on().listen()  

只监听EventParam。

eventBus.on<EventParam>().listen((EventParam data) =>
        show(data.name)
    );

第一个页面全部源码

import 'package:flutter/material.dart';
import 'package:ydcflutter_app/common/test/CartModel.dart';
import 'package:ydcflutter_app/common/test/Item.dart';
import 'package:provider/provider.dart';
import 'package:ydcflutter_app/eventbus/YDCEventBusManage.dart';
import 'package:ydcflutter_app/eventbus/EventParam.dart';
import 'package:ydcflutter_app/test/EventBusTestPage2.dart';
import 'dart:async';
class EventBusTestPage extends StatefulWidget {
  @override
  State createState() => new _EventBusTestPageState();
}

class _EventBusTestPageState extends State<EventBusTestPage> {

  BuildContext mContext;

  StreamSubscription _subscription;
  var data="";

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //监听登录事件
    _subscription=eventBus.on<EventParam>().listen((EventParam data) =>
        show(data.name)
    );
    _subscription.resume();

  }

  void show(String val) {
    setState(() {
      data= val;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold( body:Center(

      child: Builder(builder: (context) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Builder(builder: (context) {

              return Text("EventBus回传的数据: ${data}");
            }),

            Builder(builder: (context) {
              print("RaisedButton build"); //在后面优化部分会用到
              return RaisedButton(
                child: Text("跳转到第二页面"),
                onPressed: () {
                  //给购物车中添加商品,添加后总价会更新
                  //Provider.of<CartModel>(context).add(Item(10.0, 1));

                  Navigator.of(context).push(new MaterialPageRoute<Null>(
                    builder: (BuildContext context) {
                      return new EventBusTestPage2();
                    },
                  ));
                },
              );
            }),

          ],
        );
      }),
    ),
    );
  }


  Widget dividerWidget = new Container(
    //margin: const EdgeInsets.only( left: 10.0,right: 10.0),
      child: new Padding(
          padding: const EdgeInsets.only(left: 0.0, right: 0.0),
          child:
          new Divider(height: 1.0, indent: 0.0, color: Color(0xFFe5e5e5))
      )

  );

  @override
  void dispose() {
    super.dispose();
    //eventBus.destroy();
    //_subscription.resume();  //  开
    //_subscription.pause();    //  暂停
    _subscription.cancel();   //  取消

  }
}

5、在第二个触发按钮事件中页面发送一个EventParam事件,这个时候,第一个界面就会立马更新

eventBus.fire(EventParam("110",'把无用同志发配到前一个页面'));

第二个页面代码

import 'package:flutter/material.dart';
import 'package:ydcflutter_app/common/test/CartModel.dart';
import 'package:ydcflutter_app/common/test/Item.dart';
import 'package:provider/provider.dart';
import 'package:ydcflutter_app/eventbus/YDCEventBusManage.dart';
import 'package:ydcflutter_app/eventbus/EventParam.dart';
import 'package:ydcflutter_app/test/EventBusTestPage1.dart';


class EventBusTestPage2 extends StatefulWidget {
  @override
  State createState() => new _EventBusTestPage2State();
}

class _EventBusTestPage2State extends State<EventBusTestPage2> {

  BuildContext mContext;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  void _onFire() {
    //bus.emit("login",new EventParam("1",'把无用同志发配到前一个页面'));
    eventBus.fire(EventParam("110",'把无用同志发配到前一个页面'));
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold( body:Center(

      child: Builder(builder: (context) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[

            Builder(builder: (context) {
              print("RaisedButton build"); //在后面优化部分会用到
              return RaisedButton(
                child: Text("使用EventBus更新上一个页面的数据"),
                onPressed: () {
                  _onFire();
                  Navigator.of(context).pop();

                },
              );
            }),

          ],
        );
      }),
    ),
    );
  }

  Widget dividerWidget = new Container(
    //margin: const EdgeInsets.only( left: 10.0,right: 10.0),
      child: new Padding(
          padding: const EdgeInsets.only(left: 0.0, right: 0.0),
          child:
          new Divider(height: 1.0, indent: 0.0, color: Color(0xFFe5e5e5))
      )

  );

  @override
  void dispose() {
    super.dispose();
  }
}

6、EventBus还可以用在以下场景:
1、单个页面里面的父子组件之间的通信
2、可以作为整个应用的全局事件,比如Http请求在某种code值下,刷新一个或多个界面。

Flutter商城项目实战:https://github.com/dechengyang/ydc_flutter_app

如果对你有帮助,随意赏我奶粉钱吧,多谢!

微信:
在这里插入图片描述
支付宝:
在这里插入图片描述

发布了53 篇原创文章 · 获赞 58 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/XiNanHeiShao/article/details/103120165