stream

120 阅读3分钟

stream 大致框架

其他功能大体都是在这基础上延伸

stream.jpg

1. _StreamImplEvents

_StreamImplEvents<T>.jpg

DelayedEvent 即为挂起(保存/待执行)的事件, 链表结构 , _StreamImplEvents 保存了链表的头尾节点, 方便插入数据

class _StreamImplEvents<T> extends _PendingEvents<T> {
  /// 链表头节点
  _DelayedEvent? firstPendingEvent;

  /// 链表尾节点, events 插入到尾节点后面
  _DelayedEvent? lastPendingEvent;

  void add(_DelayedEvent event) {}

  void handleNext(_EventDispatch<T> dispatch) {}

  void clear() {}
}
  

由此可见_StreamImplEvents 是操作链表的类, 主要起以下作用:

  1. 链表添加事件
  2. 执行链表中的事件
  3. 清空链表

_StreamImplEvents 如何使用? 由此引入_ControllerSubscription(事件订阅者)

2. _ControllerSubscription

_BufferingStreamSubscription.jpg

订阅事件和执行事件的类, _ControllerSubscription 主要实现都靠_BufferingStreamSubscription, 相比它,多一些生命周期的控制(暂时忽略)

class _BufferingStreamSubscription<T>
    implements StreamSubscription<T>, _EventSink<T>, _EventDispatch<T> {
    
  /// 三个不同状态的回调函数
  _DataHandler<T> _onData;
  Function _onError;
  _DoneHandler _onDone;
  
  /// 链表, 外面传递过来的, 如_streamController
  _PendingEvents<T>? _pending;
  
  /// 构造方法
  _BufferingStreamSubscription(void onData(T data)?, Function? onError,
      void onDone()?, bool cancelOnError)
      : this.zoned(Zone.current, onData, onError, onDone, cancelOnError);
  /// 构造方法
  _BufferingStreamSubscription.zoned(this._zone, void onData(T data)?,
      Function? onError, void onDone()?, bool cancelOnError)
      : _state = (cancelOnError ? _STATE_CANCEL_ON_ERROR : 0),
        _onData = _registerDataHandler<T>(_zone, onData),
        _onError = _registerErrorHandler(_zone, onError),
        _onDone = _registerDoneHandler(_zone, onDone);
    
    
  void _add(T data) {
    if (_canFire) {
        /// 执行 _onData 回调
          _zone.runUnaryGuarded(_onData, data);
    } else {
        /// 懒加载, 不存在则实例化
      _StreamImplEvents<T>? pending = _pending ??= _StreamImplEvents<T>();
      
       /// 链表添加待执行事件
       final event = _DelayedData(data);
       pending.add(event);
    }
  }

  void _addError(Object error, StackTrace stackTrace) {
        /// 大体同上
  }

  void _close() {
       /// 大体同上
  }
    
}

由此可见_ControllerSubscription 大体上就是用链表保存一些待执行的事件, 不过此处事件被细分为 onData, OnError, onDone 三种

另外事件一旦被监听就会被执行, 而不是添加到链表

StreamSubscription 事件执行过程的一些状态, 如onError 执行出错了

_ControllerSubscription如何使用呢?

3._StreamController

_StreamController<T>.jpg

abstract class _StreamController<T> implements _StreamControllerBase<T> {

    // 添加监听, 方式一
    StreamSubscription<T> _subscribe(void onData(T data)?, Function? onError,
      void onDone()?, bool cancelOnError) {
  
        /// new _ControllerSubscription 
        _ControllerSubscription<T> subscription = _ControllerSubscription<T>(
        this, onData, onError, onDone, cancelOnError);

        /// 添加监听的两种方式
        /// 方式二
        if (_isAddingStream) {
          _StreamControllerAddStreamState<T> addState = _varData as dynamic;
          addState.varData = subscription;
          addState.resume();
        } else {
          _varData = subscription;
        }
    
      /// 设置 _ControllerSubscription 链表, 并执行链表中的方法
        subscription._setPendingEvents(_pendingEvents);

        return subscription;
  }
  
  // StreamSink interface.
  /// 添加监听, 方式二
  Future addStream(Stream<T> source, {bool? cancelOnError}) {

    _StreamControllerAddStreamState<T> addState =
        _StreamControllerAddStreamState<T>(
            this, _varData, source, cancelOnError ?? false);

    return addState.addStreamFuture;
  }
  
  
 /// 方式三, 方式三利用接口实现, 本质是调用_controller._subscribe,即方式一
 /// 接口即 _StreamControllerLifecycle
 Stream<T> get stream => _ControllerStream<T>(this);
  
  /// 获取创建后的监听者对象
   _ControllerSubscription<T> get _subscription {
    Object? varData = _varData;
    if (_isAddingStream) {
      _StreamControllerAddStreamState<Object?> streamState = varData as dynamic;
      varData = streamState.varData;
    }
    return varData as dynamic;
  }
}

由此可见_StreamController提供了三种创建subscription方法

  • 方式一 直接创建了一个subscription
  • 方式二 创建_StreamControllerAddStreamState 由它间接创建subscription 和 Futrue 对象
  • 方式三 通过接口调用方式一

_StreamController 有了subscription 对象, 就可以操作链表添加数据, add 、addError 、close即是对链表操作的二次封装

注意方式一添加订阅者之后, 就开始执行链表中的event事件,

 
    第一步
  /// _StreamController._subscription
  void _setPendingEvents(_PendingEvents<T>? pendingEvents) {
    if (!pendingEvents.isEmpty) {
      pendingEvents.schedule(this);
    }
  }
    
    第二步
  /// pendingEvents.schedule
  void schedule(_EventDispatch<T> dispatch) {
    scheduleMicrotask(() {
      handleNext(dispatch);
    });
  }
 
    第三步
 /// _StreamImplEvents.handleNext
 void handleNext(_EventDispatch<T> dispatch) {
    _DelayedEvent event = firstPendingEvent!;
    _DelayedEvent? nextEvent = event.next;
    firstPendingEvent = nextEvent;
    if (nextEvent == null) {
      lastPendingEvent = null;
    }
    event.perform(dispatch);
  }
    
    第四步
 /// _DelayedData.perform
  void perform(_EventDispatch<T> dispatch) {
    dispatch._sendData(value);
  }

4.应用

1.三方库get应用, rx_impl.dart 文件, 对 T value 实现监听


class GetListenable<T> extends ListNotifierSingle implements RxInterface<T> {

  StreamController<T>? _controller;

  /// 1. 创建StreamController
  StreamController<T> get subject {
    if (_controller == null) {
      _controller =
          StreamController<T>.broadcast(onCancel: addListener(_streamListener));
          
       /// 链表添加数据
      _controller?.add(_value);
    }
    return _controller!;
  }
  
  Stream<T> get stream {
    return subject.stream;
  }

  /// 链表添加事件 OnData
  void _streamListener() {
    _controller?.add(_value);
  }

  /// 链表添加事件 OnDone
  @override
  @mustCallSuper
  void close() {
    _controller?.close();
  }

  /// 监听事件
  StreamSubscription<T> listenAndPump(void Function(T event) onData,
      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
    final subscription = listen(
      onData,
      onError: onError,
      onDone: onDone,
      cancelOnError: cancelOnError,
    );
    subject.add(value);
    return subscription;
  }          

abstract class _RxImpl<T> extends GetListenable<T> with RxObjectMixin<T> {

  /// 链表添加事件 OnError
  void addError(Object error, [StackTrace? stackTrace]) {
    subject.addError(error, stackTrace);
  }

  Stream<R> map<R>(R mapper(T? data)) => stream.map(mapper);

  /// 链表添加事件 OnData
  void update(void fn(T? val)) {
    fn(value);
    subject.add(value);
  }

 
   /// 链表添加事件 OnData
  void trigger(T v) {
    var firstRebuild = this.firstRebuild;
    value = v;
    // If it's not the first rebuild, the listeners have been called already
    // So we won't call them again.
    if (!firstRebuild && !sentToStream) {
      subject.add(v);
    }
  }
}