Flutter 中的异步事件处理之_StreamController源码解析(三)

_StreamControllerLifecycle

typescript 复制代码
abstract class _StreamControllerLifecycle<T> {
  StreamSubscription<T> _subscribe(void onData(T data)?, Function? onError,
      void onDone()?, bool cancelOnError);
  void _recordPause(StreamSubscription<T> subscription) {}
  void _recordResume(StreamSubscription<T> subscription) {}
  Future<void>? _recordCancel(StreamSubscription<T> subscription) => null;
}

这段代码定义了一个名为 _StreamControllerLifecycle<T> 的抽象类,它描述了流控制器的生命周期相关的方法和功能。

  • _subscribe 方法:用于创建一个流订阅(StreamSubscription<T>)。这个方法接受四个参数,分别是数据处理回调 onData、错误处理回调 onError、完成回调 onDone,以及一个布尔值 cancelOnError,用于指示是否在出现错误时自动取消订阅。
  • _recordPause 方法:用于记录流订阅的暂停状态。这个方法在流订阅被暂停时调用,但它的实现为空,因此不执行任何特定操作。通常,它用于记录订阅的暂停状态,以便在需要时进行相应的处理。
  • _recordResume 方法:用于记录流订阅的恢复状态。与 _recordPause 类似,这个方法在流订阅恢复时调用,但它的实现为空,不执行具体操作。通常,它用于记录订阅的恢复状态。
  • _recordCancel 方法:用于记录流订阅的取消,并返回一个可能的 future(异步操作)。这个方法在流订阅被取消时调用,可以用于执行与取消相关的清理工作。方法返回一个可能为异步操作的 Future<void>,以表示取消操作的完成状态。

_EventSink

java 复制代码
/// Abstract and private interface for a place to put events.
abstract class _EventSink<T> {
  void _add(T data);
  void _addError(Object error, StackTrace stackTrace);
  void _close();
}

这段代码定义了一个名为 _EventSink<T> 的抽象和私有接口,用于将事件放置到某个地方。

  • _add 方法:用于向事件放置位置添加数据事件。它接受一个泛型类型 T 的数据作为参数。
  • _addError 方法:用于向事件放置位置添加错误事件。它接受一个错误对象 error 和一个可选的堆栈跟踪对象 stackTrace 作为参数,用于指定错误信息和相关的堆栈跟踪信息。
  • _close 方法:用于关闭事件处理。当调用此方法时,表示事件放置位置已经不再接受新的事件。

这个接口通常用于底层的事件处理机制,用于将数据事件、错误事件和关闭事件传递到相应的处理位置。在实际应用中,具体的事件处理器可以实现这个接口,以便处理和管理事件流的行为。

_EventDispatch

java 复制代码
/// Abstract and private interface for a place to send events.
///
/// Used by event buffering to finally dispatch the pending event, where
/// [_EventSink] is where the event first enters the stream subscription,
/// and may yet be buffered.

/// 用于发送事件的抽象和私有接口。 
/// 用于事件缓冲,最终分发挂起的事件。[_EventSink] 是事件首次进入流订阅的位置,可能会被缓冲。
abstract class _EventDispatch<T> {
  void _sendData(T data);
  void _sendError(Object error, StackTrace stackTrace);
  void _sendDone();
}

这段代码定义了一个名为 _EventDispatch<T> 的抽象和私有接口,用于将事件发送到某个地方。

  • _sendData 方法:用于发送数据事件。它接受一个泛型类型 T 的数据作为参数,用于发送数据事件。
  • _sendError 方法:用于发送错误事件。它接受一个错误对象 error 和一个可选的堆栈跟踪对象 stackTrace 作为参数,用于发送错误事件和相关的堆栈跟踪信息。
  • _sendDone 方法:用于发送完成事件。当调用此方法时,表示事件发送位置已经完成了事件的发送。

这个接口通常用于底层的事件处理机制,用于将数据事件、错误事件和完成事件发送到相应的处理位置。在实际应用中,具体的事件发送器可以实现这个接口,以便将事件发送到流的订阅者或其他接收位置。

_StreamControllerBase

csharp 复制代码
// Base type for implementations of stream controllers.
abstract class _StreamControllerBase<T>
    implements
        StreamController<T>,
        _StreamControllerLifecycle<T>,
        _EventSink<T>,
        _EventDispatch<T> {}

定义了一个抽象类 _StreamControllerBase<T>,它是流控制器实现的基本类型。它继承了多个接口,包括 StreamController<T>_StreamControllerLifecycle<T>_EventSink<T>_EventDispatch<T>

  • StreamController流控制器接口
  • _StreamControllerLifecycle流控制器生命周期接口
  • _EventSink事件接收器接口
  • _EventDispatch事件分发接口

_StreamController

csharp 复制代码
/// Default implementation of [StreamController].
///
/// Controls a stream that only supports a single controller.
abstract class _StreamController<T> implements _StreamControllerBase<T> {}

这个抽象类是 StreamController 的默认实现,它继承了 _StreamControllerBase<T> 接口,用于控制只支持单个控制器的流。在实际应用中,可以通过继承 _StreamController 并实现相应的方法来创建自定义的流控制器。

_state、_varData

csharp 复制代码
abstract class _StreamController<T> implements _StreamControllerBase<T> {
  // The states are bit-flags. More than one can be set at a time.
  //
  // The "subscription state" goes through the states:
  //   initial -> subscribed -> canceled.
  // These are mutually exclusive.
  // The "closed" state records whether the [close] method has been called
  // on the controller. This can be done at any time. If done before
  // subscription, the done event is queued. If done after cancel, the done
  // event is ignored (just as any other event after a cancel).

  /// The controller is in its initial state with no subscription.
  static const int _STATE_INITIAL = 0;

  /// The controller has a subscription, but hasn't been closed or canceled.
  ///
  /// Keep in sync with
  /// runtime/vm/stack_trace.cc:kStreamController_StateSubscribed.
  static const int _STATE_SUBSCRIBED = 1;

  /// The subscription is canceled.
  static const int _STATE_CANCELED = 2;

  /// Mask for the subscription state.
  static const int _STATE_SUBSCRIPTION_MASK = 3;

  // The following state relate to the controller, not the subscription.
  // If closed, adding more events is not allowed.
  // If executing an [addStream], new events are not allowed either, but will
  // be added by the stream.

  /// The controller is closed due to calling [close].
  ///
  /// When the stream is closed, you can neither add new events nor add new
  /// listeners.
  static const int _STATE_CLOSED = 4;

  /// The controller is in the middle of an [addStream] operation.
  ///
  /// While adding events from a stream, no new events can be added directly
  /// on the controller.
  static const int _STATE_ADDSTREAM = 8;

  /// Field containing different data depending on the current subscription
  /// state.
  ///
  /// If [_state] is [_STATE_INITIAL], the field may contain a [_PendingEvents]
  /// for events added to the controller before a subscription.
  ///
  /// While [_state] is [_STATE_SUBSCRIBED], the field contains the subscription.
  ///
  /// When [_state] is [_STATE_CANCELED] the field is currently not used,
  /// and will contain `null`.
  @pragma("vm:entry-point")
  Object? _varData;

  /// Current state of the controller.
  @pragma("vm:entry-point")
  int _state = _STATE_INITIAL;
  • 状态是位标志:状态是通过位标志(bit-flags)表示的,这意味着可以同时设置多个状态。

  • 订阅状态:订阅状态是指控制器与订阅之间的关系。它经历了以下状态转换:

    • initial(初始状态) -> subscribed(已订阅) -> canceled(已取消)。
    • 这些状态是相互排斥的,即在同一时间只能处于其中一个状态。
  • 已关闭状态 :已关闭状态记录了是否已调用了控制器的 [close] 方法。可以在任何时间调用 [close] 方法。如果在订阅之前关闭,完成事件(done event)会被排队等待。如果在取消订阅之后关闭,完成事件将被忽略,就像在取消订阅之后的任何其他事件一样。

二进制状态码解释:

  • _STATE_INITIAL:初始状态,控制器没有订阅。
  • _STATE_SUBSCRIBED:已订阅状态,控制器有一个订阅但尚未关闭或取消。
  • _STATE_CANCELED:已取消状态,订阅已被取消。
  • _STATE_CLOSED:已关闭状态,控制器由于调用了 close 方法而关闭,不允许添加新事件或监听器。
  • _STATE_ADDSTREAM:正在执行 addStream 操作中,不允许直接添加新事件到控制器上。

_varData 字段解释:

  • 包含不同数据的字段,取决于当前的订阅状态。
  • 如果 _state_STATE_INITIAL ,字段可能包含在订阅之前添加到控制器的 _PendingEvents
  • _state_STATE_SUBSCRIBED 时,字段包含订阅。
  • _state_STATE_CANCELED 时,字段当前未使用,并将包含 null

_doneFuture

arduino 复制代码
/// Future completed when the stream sends its last event.
///
/// This is also the future returned by [close].
// TODO(lrn): Could this be stored in the varData field too, if it's not
// accessed until the call to "close"? Then we need to special case if it's
// accessed earlier, or if close is called before subscribing.
_Future<void>? _doneFuture;

这段代码定义了一个 _doneFuture 字段,它是一个 _Future<void>? 类型的对象,表示当流发送其最后一个事件时将完成的未来。

这个 _doneFuture 字段用于表示一个异步操作的未来(Future),该操作在流发送最后一个事件时完成。通常情况下,这个未来会在流关闭(close)方法被调用时返回,以表示流已经完成。这个未来可以用于等待流的完成状态,或者处理流关闭后的清理操作。

onListen、onPause、onResume、onCancel

csharp 复制代码
void Function()? onListen;
void Function()? onPause;
void Function()? onResume;
FutureOr<void> Function()? onCancel;

这段代码定义了一组回调函数,用于处理流控制器的不同事件。以下是对这些回调函数的解释:

  • onListen:当流被监听时触发的回调函数。这个回调函数将在有订阅者监听流时被调用。通常用于执行在流开始被监听时需要进行的操作。
  • onPause:当流被暂停时触发的回调函数。这个回调函数将在流被暂停时被调用。暂停意味着流的事件传递被停止,通常用于执行在流暂停时需要进行的操作。需要注意,暂停相关的回调在广播流控制器中不受支持。
  • onResume:当流被恢复时触发的回调函数。这个回调函数将在流被恢复时被调用。恢复意味着流的事件传递被重新启动,通常用于执行在流恢复时需要进行的操作。需要注意,恢复相关的回调在广播流控制器中不受支持。
  • onCancel:当流被取消订阅时触发的回调函数。这个回调函数将在流的订阅者取消订阅时被调用。它可以返回一个 FutureOr<void>,用于执行与取消订阅相关的异步操作。如果没有需要执行的异步操作,可以返回 null。通常用于执行在取消订阅时需要进行的清理操作。

这些回调函数允许你在流的不同生命周期阶段执行自定义的操作,以满足特定的需求。它们可以用于在流的监听、暂停、恢复和取消订阅等事件发生时执行相应的逻辑。

_StreamController初始化

kotlin 复制代码
_StreamController(this.onListen, this.onPause, this.onResume, this.onCancel);

这段代码是一个构造函数 _StreamController,用于创建 _StreamController 实例。它接受四个参数 onListenonPauseonResumeonCancel,分别代表监听、暂停、恢复和取消订阅时的回调函数。

_isCanceled

arduino 复制代码
/// Whether a listener has existed and been canceled.
///
/// After this, adding more events will be ignored.
bool get _isCanceled => (_state & _STATE_CANCELED) != 0;
  • 检查是否存在已经存在的监听器并且已经被取消订阅。
  • 在这种情况下,添加更多的事件将被忽略。

按位与操作会将两个二进制数的对应位进行逐位比较,如果两个位都为1,则结果位为1,否则为0

  • _state的默认值是00的二进制是000000000
  • _STATE_CANCELED的没默认值是22的二进制是00000010
  • _state_STATE_CANCELED变量按位与运算的结果是00000000, 转换成十进制就是0

这个属性的作用是检查当前流的状态,看是否存在已经存在的监听器并且这些监听器已经被取消订阅。如果 _state 的值按位与 _STATE_CANCELED 后不等于零,就表示已经存在监听器并且已经被取消订阅,此时添加更多的事件将被忽略,因为流已经处于取消订阅状态。这个属性用于控制流的行为,以确保在流取消订阅后不再接受新的事件。

hasListener

arduino 复制代码
/// Whether there is an active listener.
检查是否存在活跃的监听器。
bool get hasListener => (_state & _STATE_SUBSCRIBED) != 0;

这个属性的作用是检查当前流的状态,看是否存在活跃的监听器。使用按位与运算符 &_state_STATE_SUBSCRIBED 进行按位与操作。如果结果不等于0,就表示 _state 中的 _STATE_SUBSCRIBED 位被设置为1,即存在活跃的监听器。如果结果等于0,则表示没有活跃的监听器。

这个属性可以用于判断是否有订阅者正在监听流,以便在需要时采取相应的行动。如果存在活跃的监听器,可以执行与之相关的操作,否则可以采取不同的处理逻辑。

_isInitialState

arduino 复制代码
/// Whether there has not been a listener yet.
检查是否还没有出现过监听器。
bool get _isInitialState =>
    (_state & _STATE_SUBSCRIPTION_MASK) == _STATE_INITIAL;

这个属性的作用是检查当前流的状态,看是否处于初始状态,即还没有出现过监听器。它使用按位与运算符 &_state_STATE_SUBSCRIPTION_MASK 进行按位与操作,并将结果与 _STATE_INITIAL 进行比较。

_STATE_SUBSCRIPTION_MASK 是一个用于掩码操作的常量,用于提取与订阅状态相关的位。如果按位与的结果等于 _STATE_INITIAL,就表示当前流还没有出现过监听器,即还没有订阅者。

这个属性通常用于确定流是否处于初始状态,以便在需要时采取相应的初始化操作。如果还没有出现过监听器,可以执行特定的初始化逻辑。

isClosed

ini 复制代码
bool get isClosed => (_state & _STATE_CLOSED) != 0;

这个属性的作用是检查当前流控制器的状态,看是否已经被关闭。使用按位与运算符 &_state_STATE_CLOSED 进行按位与操作。如果结果不等于0,就表示 _state 中的 _STATE_CLOSED 位被设置为1,即流控制器已经关闭。

这个属性通常用于判断流控制器的状态,以确定是否可以向其添加新的事件或监听器。如果流控制器已经关闭,就表示不再接受新的事件或监听器。

isPaused

ini 复制代码
bool get isPaused =>
    hasListener ? _subscription._isInputPaused : !_isCanceled;

这个属性的作用是根据流的当前状态来确定是否处于暂停状态。具体的判断逻辑如下:

  • 如果存在活跃的监听器(hasListenertrue),则通过 _subscription._isInputPaused 属性来确定流是否被暂停。_subscription 是与流关联的订阅对象,它具有 _isInputPaused 属性用于表示输入是否被暂停。
  • 如果不存在活跃的监听器(hasListenerfalse),则检查 _isCanceled 属性,如果 _isCanceledtrue,表示流已经被取消订阅,流不再被暂停。如果 _isCanceledfalse,表示流仍然处于未订阅状态,也不会被暂停。

这个属性的目的是根据流的状态来确定是否可以继续向流中添加事件。如果流被暂停,添加事件可能会被暂时忽略,直到流恢复。如果流已经取消订阅,添加事件将被忽略。

_isAddingStream

ini 复制代码
bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0;

这个属性的作用是检查当前流的状态,看是否正在执行 addStream 操作。它使用按位与运算符 &_state_STATE_ADDSTREAM 进行按位与操作。如果结果不等于0,就表示 _state 中的 _STATE_ADDSTREAM 位被设置为1,即流正在执行 addStream 操作。

这个属性通常用于判断流的状态,以确定是否可以向其添加更多事件。如果流正在执行 addStream 操作,添加事件可能会被暂时延迟,直到 addStream 操作完成。在这期间,直接添加事件到流可能会被忽略。

_mayAddEvent

arduino 复制代码
/// New events may not be added after close, or during addStream.
bool get _mayAddEvent => (_state < _STATE_CLOSED);

这个属性的作用是根据流的状态来确定是否可以向流中添加新的事件。具体的判断逻辑如下:

  • 如果 _state 的值小于 _STATE_CLOSED,则表示可以添加新的事件。这是因为 _STATE_CLOSED 表示流已经关闭,而小于 _STATE_CLOSED 的状态表示流还处于打开状态,可以继续添加事件。
  • 如果 _state 的值大于等于 _STATE_CLOSED,则表示无法添加新的事件。这是因为流已经关闭(_STATE_CLOSED)或正在执行 addStream 操作(_STATE_ADDSTREAM),在这些情况下,不能添加新的事件。

这个属性的目的是确保在适当的时候向流中添加事件,避免在不合适的情况下尝试添加事件,从而保持流的状态一致性。

相关推荐
前端 贾公子1 小时前
axios如何利用promise无痛刷新token
前端
新生派2 小时前
HTML<hgroup>标签
前端·html
timer_0173 小时前
Tailwind CSS 正式发布了 4.0 版本
前端·css
答题卡上的情书4 小时前
uniapp版本升级
前端·javascript·uni-app
枫叶丹45 小时前
【HarmonyOS之旅】基于ArkTS开发(三) -> 兼容JS的类Web开发(三)
开发语言·前端·javascript·华为·harmonyos
酷爱码5 小时前
HTML5+SVG+CSS3实现雪中点亮的圣诞树动画效果源码
前端·css3·html5
有杨既安然5 小时前
Vue.js组件开发深度指南:从零到可复用的艺术
前端·javascript·vue.js·npm
步、步、为营7 小时前
C#牵手Blazor,解锁跨平台Web应用开发新姿势
开发语言·前端·c#
i7i8i9com8 小时前
node-sass已经废弃了,需要替换成以下方式
前端·css·sass
我命由我123459 小时前
脚本运行禁止:npm 无法加载文件,因为在此系统上禁止运行脚本
前端·javascript·前端框架·npm·node.js·html·js