前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「 flutter 必知必会 」最强事件发布/订阅框架方案 event_bus 全局事件总线使用解析

「 flutter 必知必会 」最强事件发布/订阅框架方案 event_bus 全局事件总线使用解析

作者头像
圆号本昊
发布2021-12-30 16:32:45
1.4K0
发布2021-12-30 16:32:45
举报
文章被收录于专栏:github@hornhuanggithub@hornhuang

一、前言

  • EventBus是全局事件总线,底层通过Stream来实现;它可以实现不同页面的跨层访问,通过Stream的机制来实现不同widget之间的状态共享.

二、作用

  • 举个例子:

你有一个主界面,里面有一些信息可能会修改,但触发源不在该界面,是在其他的界面触发了一些事件后,首页的内容需要做修改。如果没有EventBus,也有很多的方式可以实现,譬如定义全局静态变量、或者定义个CallBack接口传出去等等。不管怎样,总是要把主页和触发源关联起来,这是相当难受的,这不但会导致代码量暴涨,同时还会导致耦合度极高,不得不写的这个引用让人如鲠在喉。

三、使用

flutter 中使用 eventbus 主要可以归纳为如下步骤:

  1. 实例化 eventbus
  2. 定义消息 event 对象
  3. 创建监听器
  4. 发送消息
  5. 接收消息
  • 下文我将以网络请求为例进行解析
3.1 实例化 eventbus
  • 由于 eventbus 是可能在不同类里调用的
  • 就比如说本文的网络请求使用 eventbus ,那么网络请求可能发生在很多歌类的代码里
  • 所以不能将其单独在某个特定页面的类里创建,而需要让其变成全局的变量
  • 这里我们新建一个文件:event_bus.dart 用它来专门存储 event_bus 对象
代码语言:javascript
复制
import 'package:event_bus/event_bus.dart';

EventBus eventBus = new EventBus();
3.2 定义消息 event 对象
  • 有学过 AndroidiOS 或者其他任意技术的同学都知道
  • 在全局发送一个消息是需要携带一个对象,来存储消息的内容
  • 其实 flutterevent_bus 也是如此
  • 所以我们新建一个文件 http_event.dart 来存放这种需要传递的消息体
  • 当然本文限于篇幅,就以网络请求错误/失败为例
代码语言:javascript
复制
class HttpErrorEvent {
  final int code;

  final String message;

  HttpErrorEvent(this.code, this.message);
}
3.3 创建监听器
  • 跟 3.2 类似,我们针对每种类型的事件(每个 eventbus),需要建立一个监听
  • 并把这个监听混入相应的页面(widget 中)来达到监听效果
  • 所以,我们首先新建一个文件 http_listener.dart
代码语言:javascript
复制
import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:fluttertoast/fluttertoast.dart';

import 'event_bus.dart';
import 'home_page.dart';
import 'http_event.dart';

mixin HttpErrorListener on State<MyHomePage> {
  StreamSubscription stream;

  BuildContext _context;

  @override
  void initState() {
    super.initState();

    ///Stream演示event bus
    stream = eventBus.on<HttpErrorEvent>().listen((event) {
      errorHandleFunction(event.code, event.message);
    });
  }

  @override
  void dispose() {
    super.dispose();
    if (stream != null) {
      stream.cancel();
      stream = null;
    }
  }

  ///网络错误提醒
  errorHandleFunction(int code, message) {
    switch (code) {
      case 404:
        showToast("404: ${message}");
        break;
      default:
        showToast("unknown: ${message}");
        break;
    }
  }

  showToast(String message) {
    Fluttertoast.showToast(
        msg: message,
        gravity: ToastGravity.CENTER,
        toastLength: Toast.LENGTH_LONG);
  }
}
  • 这里使用 私有的 _context 是因为此时 StatecontextFlutterReduxApp 而不是 MaterialApp
  • 所以如果直接用 context 是会获取不到 MaterialAppLocalizations 哦。

showToast 是一个三方的吐司库 可以再 dependences 中添加 fluttertoast: ^7.1.1 即可

3.4 发送消息
  • 发送消息时只要调用 eventBus.fire(...) 即可
  • 参数是需要传递的消息对象
  • 比如本文的玩过请求失败就可以是 HttpErrorEvent(404, "找不到网页")
代码语言:javascript
复制
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

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

  void _incrementCounter() {
    eventBus.fire(HttpErrorEvent(404, "找不到网页"));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Text(
        'flutter event bus sample',
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
3.5 接收消息
  • 接收消息其实就是把监听器混入的过程
  • 混入对象可以是一个单例(比如收到消息后上传日志,或者后台做什么动作),也可以是一个页面(比如刷新下页面,或者本文网络请求的例子,请求失败需要弹出一个 Toast),等等诸如此类
  • 这里就按网络请求的例子,我们在 State 对象后混入:with HttpErrorListener 即可
代码语言:javascript
复制
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> with HttpErrorListener {
  // ...
}
  • 这样一来,当 3. 4 中发送消息后,_MyHomePageState 的监听就会收到消息对象
  • 并调用 HttpErrorListener 中的 errorHandleFunction 方法去触发其中的 showToast(String message) 方法,从而在屏幕上弹出一个 Toast

为了方便大家理解,对于 Dart 中混合 mixin、on、with 语法陌生的同学可以看这篇文章 Flutter 知识梳理 (Dart) - implements, extends, mixin 的理解

四、总结

  • 对于复杂的程序 event_bus 能有效的解耦,把本该有联系的需要传引用的给简化了,由它来分发事件了。这在某些时候和Android里的broadcast有点像,都是能通知很多个观察者,只不过更简便一点。
  • 为了方便大家学习,我把代码上传到了 githubbilibili-workspace/flutter_eventbus_sample
  • 如果还有疑问,或者有更好的方法,欢迎大家在评论区提出
  • 感谢大家的三连或者关注支持,我们下期文章再见
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-03-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
  • 二、作用
  • 三、使用
    • 3.1 实例化 eventbus
      • 3.2 定义消息 event 对象
        • 3.3 创建监听器
          • 3.4 发送消息
            • 3.5 接收消息
            • 四、总结
            相关产品与服务
            事件总线
            腾讯云事件总线(EventBridge)是一款安全,稳定,高效的云上事件连接器,作为流数据和事件的自动收集、处理、分发管道,通过可视化的配置,实现事件源(例如:Kafka,审计,数据库等)和目标对象(例如:CLS,SCF等)的快速连接,当前 EventBridge 已接入 100+ 云上服务,助力分布式事件驱动架构的快速构建。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档