flutter bus 总线设计(iOS通知)

2022-01-26  本文已影响0人  简单coder

本篇是利用 stremcontroller.broadcast 实现了类似 iOS 通知功能,具备跨组件1对多消息通知.
业务场景平时也十分多,比如用户更新用户信息,消息接收修改会话,红点,消息列表更新会话等等,都是需要多处监听,比如游客模式到用户登录,十几个页面的更新
说到游客模式到登录,getx 中多语言切换使用了forceAppUpdate感兴趣的可以看看这里,不知道是不是个黑科技
或者可以根App 中加个 GetBuilder,执行 update(),毕竟游客模式到登录模式需要刷的页面太多了.

回归正题, bus项目代码也十分简单,所以直接上代码 附带加一些说明.

import 'dart:async';

import 'package:event_bus/event_bus.dart';
import 'package:flutter_psd/common/services/bus/index.dart';

// MARK: - --------------------------------------busName
class EventName {
  /// 用户信息更新
  static const user_info = "user_info";
}

// MARK: - --------------------------------------bus
final bus = Bus();

class Bus {
  StreamController _streamController;
  StreamController get streamController => _streamController;
  Bus({bool sync = false})
      : _streamController = StreamController.broadcast(sync: sync);

  /// 监听事件
  Stream<dynamic> on(String eventName) {
    return streamController.stream
        .where((event) {
          try {
            return (event as BusEvent).eventName == eventName;
          } catch (e) {
            return false;
          }
        })
        .map((event) => (event as BusEvent).data)
        .cast<dynamic>();
  }

  /// 发送事件
  void emit(String eventName, {dynamic data}) {
    var event = BusEvent(eventName: eventName, data: data);
    streamController.add(event);
  }

  /// 销毁事件
  void fire(StreamSubscription? subscription) {
    subscription?.cancel();
  }

  void destroy() {
    _streamController.close();
  }
}

首先要说明的是,因为这是应用内框架,所有我设计的代码,都是以我认为比较好的实现来写的,如果大家有各自更好的思路,这里也希望抛砖引玉.

我这里就不讲什么单例写法了,直接 new 了一个全局对象做单例,比较是自己的项目,自己遵守好规范即可,bus类总共主要就三个方法.

监听事件

/// 监听事件
  Stream<dynamic> on(String eventName) {
    return streamController.stream
        .where((event) {
          try {
            return (event as BusEvent).eventName == eventName;
          } catch (e) {
            return false;
          }
        })
        .map((event) => (event as BusEvent).data)
        .cast<dynamic>();
  }

我设计的是你监听事件名,然后我传给你我能提供的数据.
使用时

userInfoSubs = bus.on(EventName.user_info).listen((event) {
      update();
    });

pub.dev 上有一个比较高星的三方event_bus,我其实也是按照他的源码改成我自己的框架,他在监听方面推荐我们使用强类型监听转换,这样做可以强制接收类型,但需要 new class,但我用习惯了 iOS 的通知,我个人更愿意的是对消息的事件名做声明,毕竟是做项目,接收数据 dynamic 大家都应该知道业务中自己需要的是啥,如果真不喜欢,也可以自己做一层 transform(compactMap).

//event_bus 源码 on 方法
Stream<T> on<T>() {
    if (T == dynamic) {
      return streamController.stream as Stream<T>;
    } else {
      return streamController.stream.where((event) => event is T).cast<T>();
    }
  }

发送数据

/// 发送事件
  void emit(String eventName, {dynamic data}) {
    var event = BusEvent(eventName: eventName, data: data);
    streamController.add(event);
  }

使用时

bus.emit(EventName.user_info);

emit 是因为 bus 这个概念是我在接触 vue 时知道的,当时他们使用的发送都是 emit,所以这里我也就没有使用 iOS 通知的 post,其实 String做参数名还不能够做到足够的类型约束,如果可以使用 swift 的 protocol 做限制,就可以不允许他们手写事件名,我对数据接收 data 是可以允许做dynamic,但是我不能接收事件名被直接写 string.

销毁事件

/// 销毁事件
  void fire(StreamSubscription? subscription) {
    subscription?.cancel();
  }

本来 stream 可以做到自己手动销毁,但是我想强调的是规范,框架这东西,规范占了一大部分,如果不遵守规范,再牛的框架也会被后来接手者腐蚀,何况我这种功能随手写的框架.

上一篇下一篇

猜你喜欢

热点阅读