_StreamControllerLifecycle
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
/// 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(接口)
/// 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
// 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
/// 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
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
/// 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
void Function()? onListen;
void Function()? onPause;
void Function()? onResume;
FutureOr<void> Function()? onCancel;
这段代码定义了一组回调函数,用于处理流控制器的不同事件。以下是对这些回调函数的解释:
onListen:当流被监听时触发的回调函数。这个回调函数将在有订阅者监听流时被调用。通常用于执行在流开始被监听时需要进行的操作。onPause:当流被暂停时触发的回调函数。这个回调函数将在流被暂停时被调用。暂停意味着流的事件传递被停止,通常用于执行在流暂停时需要进行的操作。需要注意,暂停相关的回调在广播流控制器中不受支持。onResume:当流被恢复时触发的回调函数。这个回调函数将在流被恢复时被调用。恢复意味着流的事件传递被重新启动,通常用于执行在流恢复时需要进行的操作。需要注意,恢复相关的回调在广播流控制器中不受支持。onCancel:当流被取消订阅时触发的回调函数。这个回调函数将在流的订阅者取消订阅时被调用。它可以返回一个FutureOr<void>,用于执行与取消订阅相关的异步操作。如果没有需要执行的异步操作,可以返回null。通常用于执行在取消订阅时需要进行的清理操作。
这些回调函数允许你在流的不同生命周期阶段执行自定义的操作,以满足特定的需求。它们可以用于在流的监听、暂停、恢复和取消订阅等事件发生时执行相应的逻辑。
_StreamController初始化
_StreamController(this.onListen, this.onPause, this.onResume, this.onCancel);
这段代码是一个构造函数 _StreamController,用于创建 _StreamController 实例。它接受四个参数 onListen、onPause、onResume 和 onCancel,分别代表监听、暂停、恢复和取消订阅时的回调函数。
_isCanceled
/// 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的默认值是0。0的二进制是000000000_STATE_CANCELED的没默认值是2。2的二进制是00000010_state和_STATE_CANCELED变量按位与运算的结果是00000000, 转换成十进制就是0
这个属性的作用是检查当前流的状态,看是否存在已经存在的监听器并且这些监听器已经被取消订阅。如果 _state 的值按位与 _STATE_CANCELED 后不等于零,就表示已经存在监听器并且已经被取消订阅,此时添加更多的事件将被忽略,因为流已经处于取消订阅状态。这个属性用于控制流的行为,以确保在流取消订阅后不再接受新的事件。
hasListener
/// Whether there is an active listener.
检查是否存在活跃的监听器。
bool get hasListener => (_state & _STATE_SUBSCRIBED) != 0;
这个属性的作用是检查当前流的状态,看是否存在活跃的监听器。使用按位与运算符 & 将 _state 和 _STATE_SUBSCRIBED 进行按位与操作。如果结果不等于0,就表示 _state 中的 _STATE_SUBSCRIBED 位被设置为1,即存在活跃的监听器。如果结果等于0,则表示没有活跃的监听器。
这个属性可以用于判断是否有订阅者正在监听流,以便在需要时采取相应的行动。如果存在活跃的监听器,可以执行与之相关的操作,否则可以采取不同的处理逻辑。
_isInitialState
/// 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
bool get isClosed => (_state & _STATE_CLOSED) != 0;
这个属性的作用是检查当前流控制器的状态,看是否已经被关闭。使用按位与运算符 & 将 _state 与 _STATE_CLOSED 进行按位与操作。如果结果不等于0,就表示 _state 中的 _STATE_CLOSED 位被设置为1,即流控制器已经关闭。
这个属性通常用于判断流控制器的状态,以确定是否可以向其添加新的事件或监听器。如果流控制器已经关闭,就表示不再接受新的事件或监听器。
isPaused
bool get isPaused =>
hasListener ? _subscription._isInputPaused : !_isCanceled;
这个属性的作用是根据流的当前状态来确定是否处于暂停状态。具体的判断逻辑如下:
- 如果存在活跃的监听器(
hasListener为true),则通过_subscription._isInputPaused属性来确定流是否被暂停。_subscription是与流关联的订阅对象,它具有_isInputPaused属性用于表示输入是否被暂停。 - 如果不存在活跃的监听器(
hasListener为false),则检查_isCanceled属性,如果_isCanceled为true,表示流已经被取消订阅,流不再被暂停。如果_isCanceled为false,表示流仍然处于未订阅状态,也不会被暂停。
这个属性的目的是根据流的状态来确定是否可以继续向流中添加事件。如果流被暂停,添加事件可能会被暂时忽略,直到流恢复。如果流已经取消订阅,添加事件将被忽略。
_isAddingStream
bool get _isAddingStream => (_state & _STATE_ADDSTREAM) != 0;
这个属性的作用是检查当前流的状态,看是否正在执行 addStream 操作。它使用按位与运算符 & 将 _state 与 _STATE_ADDSTREAM 进行按位与操作。如果结果不等于0,就表示 _state 中的 _STATE_ADDSTREAM 位被设置为1,即流正在执行 addStream 操作。
这个属性通常用于判断流的状态,以确定是否可以向其添加更多事件。如果流正在执行 addStream 操作,添加事件可能会被暂时延迟,直到 addStream 操作完成。在这期间,直接添加事件到流可能会被忽略。
_mayAddEvent
/// 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),在这些情况下,不能添加新的事件。
这个属性的目的是确保在适当的时候向流中添加事件,避免在不合适的情况下尝试添加事件,从而保持流的状态一致性。
_pendingEvents
// Returns the pending events.
// Pending events are events added before a subscription exists.
// They are added to the subscription when it is created.
// Pending events, if any, are kept in the _varData field until the
// stream is listened to.
// While adding a stream, pending events are moved into the
// state object to allow the state object to use the _varData field.
_PendingEvents<T>? get _pendingEvents {
assert(_isInitialState);
if (!_isAddingStream) {
return _varData as dynamic;
}
_StreamControllerAddStreamState<T> state = _varData as dynamic;
return state.varData;
}
这个 _pendingEvents 属性的作用是获取挂起的事件,即在订阅存在之前添加到流中的事件。它包含以下几个关键点:
- 首先,通过断言
_isInitialState来确保流处于初始状态,只有在初始状态下才存在挂起的事件。 - 接着,通过检查
_isAddingStream属性,来判断是否正在执行addStream操作。如果没有执行addStream操作,挂起的事件将保存在_varData字段中,并且可以直接返回。 - 如果正在执行
addStream操作,那么挂起的事件将被移动到与addStream操作相关的状态对象中(_StreamControllerAddStreamState<T>),然后从状态对象中获取挂起事件。
总之,这个属性用于获取挂起的事件,这些事件是在订阅创建之前添加到流中的事件。挂起事件在订阅创建后会被逐一处理。
_ensurePendingEvents
// Returns the pending events, and creates the object if necessary.
_PendingEvents<T> _ensurePendingEvents() {
assert(_isInitialState);
if (!_isAddingStream) {
Object? events = _varData;
if (events == null) {
_varData = events = _PendingEvents<T>();
}
return events as dynamic;
}
_StreamControllerAddStreamState<T> state = _varData as dynamic;
Object? events = state.varData;
if (events == null) {
state.varData = events = _PendingEvents<T>();
}
return events as dynamic;
}
这个 _ensurePendingEvents 方法的作用是确保存在挂起的事件对象,并返回该对象。它包含以下几个关键点:
- 首先,通过断言
_isInitialState来确保流处于初始状态,只有在初始状态下才存在挂起的事件。 - 接着,通过检查
_isAddingStream属性,来判断是否正在执行addStream操作。如果没有执行addStream操作,就表示挂起的事件应该保存在_varData字段中。 - 如果没有挂起的事件对象(
events == null),则创建一个新的_PendingEvents<T>对象,并将它赋值给_varData字段,以便后续使用。 - 如果正在执行
addStream操作,那么挂起的事件应该保存在与addStream操作相关的状态对象中。同样,如果没有挂起的事件对象,也会创建一个新的_PendingEvents<T>对象并赋值给状态对象。 - 最后,将获取到的挂起的事件对象返回,确保它存在并可以用于存储挂起的事件。
_subscription
// Get the current subscription.
// If we are adding a stream, the subscription is moved into the state
// object to allow the state object to use the _varData field.
// 获取当前的订阅对象。
// 如果我们正在添加一个流,订阅对象将移动到状态对象中,以允许状态对象使用 _varData 字段。
_ControllerSubscription<T> get _subscription {
assert(hasListener);
Object? varData = _varData;
if (_isAddingStream) {
_StreamControllerAddStreamState<Object?> streamState = varData as dynamic;
varData = streamState.varData;
}
return varData as dynamic;
}
这个 _subscription 属性的作用是获取当前的订阅对象,即表示对流的监听器。它包含以下几个关键点:
- 首先,通过断言
hasListener来确保当前存在活跃的监听器。如果没有活跃的监听器,则无法获取订阅对象。 - 接着,通过访问
_varData字段获取当前的订阅对象。这个订阅对象可以包含有关订阅的信息。 - 如果正在执行
addStream操作(_isAddingStream为真),则需要将订阅对象从状态对象中移动出来。在执行addStream操作期间,订阅对象会被暂时存储在与addStream操作相关的状态对象中。 - 最后,将获取到的订阅对象返回,以便后续使用。
总之,这个属性用于获取当前的订阅对象,如果正在执行 addStream 操作,则从状态对象中获取订阅对象,确保在不同状态下都可以正确获取到订阅对象。
_badEventState
/// Creates an error describing why an event cannot be added.
///
/// The reason, and therefore the error message, depends on the current state.
/// 创建一个错误对象,描述为什么无法添加事件。
Error _badEventState() {
if (isClosed) {
return StateError("Cannot add event after closing");
}
assert(_isAddingStream);
return StateError("Cannot add event while adding a stream");
}
这个 _badEventState 方法的作用是根据当前的状态创建一个错误对象,用于描述为什么无法添加事件。它包含以下几个关键点:
- 首先,通过检查
isClosed属性来判断流控制器是否已关闭。如果已关闭,表示无法再添加事件,因此创建一个StateError错误对象,其中包含错误消息 "Cannot add event after closing",表示无法在关闭后添加事件。 - 如果流控制器正在执行
addStream操作(_isAddingStream为真),则表示正在添加流,而不允许直接添加事件。因此,创建一个StateError错误对象,其中包含错误消息 "Cannot add event while adding a stream",表示在添加流的过程中无法添加事件。
总之,这个方法用于根据当前状态创建一个错误对象,用于描述为什么无法添加事件,具体错误消息取决于流控制器的状态。
输入事件、数据(实现EventSink interface)
_add
// Add data event, used both by the [addStream] events and by [add].
添加数据事件,被 [addStream] 事件和 [add] 使用。
void _add(T value) {
if (hasListener) {
_sendData(value); /// _EventDispatch 中定义的接口方法
} else if (_isInitialState) {
_ensurePendingEvents().add(_DelayedData<T>(value));
}
}
这个 _add 方法的作用是将数据事件添加到流中。它包含了以下几个步骤:
- 首先,通过检查
hasListener属性,判断是否存在活跃的监听器。如果存在活跃的监听器,就调用_sendData方法将数据事件添加到流中。 - 如果没有活跃的监听器,就进一步检查
_isInitialState属性,判断流是否还处于初始状态。如果流处于初始状态,表示还没有出现监听器,那么需要确保存在一个挂起事件列表,并将数据事件包装成_DelayedData对象添加到挂起事件列表中。
总之,这个方法用于添加数据事件到流中,如果流已经处于监听状态,数据事件会立即传递给监听器,否则会将数据事件挂起,等待有监听器时再传递。这样可以确保数据事件不会丢失,并根据流的状态进行适当的处理。
_addError
添加错误事件,被 [addStream] 事件和 [addError] 使用。
void _addError(Object error, StackTrace stackTrace) {
if (hasListener) {
_sendError(error, stackTrace); /// _EventDispatch 中定义的接口方法
} else if (_isInitialState) {
_ensurePendingEvents().add(_DelayedError(error, stackTrace));
}
}
这个 _addError 方法的作用是将错误事件添加到流中。它包含了以下几个步骤:
- 首先,通过检查
hasListener属性,判断是否存在活跃的监听器。如果存在活跃的监听器,就调用_sendError方法将错误事件添加到流中,并传递错误和堆栈信息。 - 如果没有活跃的监听器,就进一步检查
_isInitialState属性,判断流是否还处于初始状态。如果流处于初始状态,表示还没有出现监听器,那么需要确保存在一个挂起事件列表,并将错误事件和堆栈信息包装成_DelayedError对象添加到挂起事件列表中。
总之,这个方法用于添加错误事件到流中,如果流已经处于监听状态,错误事件会立即传递给监听器,否则会将错误事件挂起,等待有监听器时再传递。这样可以确保错误事件不会丢失,并根据流的状态进行适当的处理。
_close
void _close() {
// End of addStream stream.
assert(_isAddingStream);
_StreamControllerAddStreamState<T> addState = _varData as dynamic;
_varData = addState.varData;
_state &= ~_STATE_ADDSTREAM;
addState.complete();
}
这个 _close 方法的作用是用于结束 addStream 操作中的流。它包含了以下几个步骤:
- 首先,通过断言
assert(_isAddingStream)来确保当前流处于执行addStream操作的状态,否则会抛出断言错误。 - 然后,通过将
_varData强制转换为_StreamControllerAddStreamState<T>类型,获取与addStream操作相关的状态信息。_varData是流控制器中的一个属性,用于存储与不同状态相关的数据。 - 接着,将
_varData更新为addState.varData,以清除与addStream操作相关的状态信息。 - 使用按位与运算符
&和按位取反操作符~,将流的状态中的_STATE_ADDSTREAM位清除,表示addStream操作结束。 - 最后,调用
addState.complete()完成addStream操作的状态,以通知相关的异步操作已经完成。
总之,这个方法用于结束 addStream 操作中的流,清除相关的状态信息,并完成异步操作。
add(_StreamController对外暴露的add接口)
/// Send or enqueue a data event.
/// 发送或排队一个数据事件。
void add(T value) {
if (!_mayAddEvent) throw _badEventState();
_add(value);
}
这个 add 方法的作用是向流中添加一个数据事件,但在添加之前会进行状态检查:
- 首先,通过调用
_mayAddEvent属性来检查是否可以添加新的事件。_mayAddEvent属性会根据流的状态来确定是否允许添加事件。如果不允许添加事件,将会抛出异常_badEventState()。 - 如果允许添加事件,就调用
_add(value)方法将数据事件添加到流中。
总之,这个方法用于向流中添加数据事件,但在添加之前会进行状态检查,确保在合适的时候添加事件,避免不合适的操作。如果不允许添加事件,将抛出异常以指示错误状态。
addError(_StreamController对外暴露的addError接口)
/// Send or enqueue an error event.
void addError(Object error, [StackTrace? stackTrace]) {
checkNotNullable(error, "error");
if (!_mayAddEvent) throw _badEventState();
AsyncError? replacement = Zone.current.errorCallback(error, stackTrace);
if (replacement != null) {
error = replacement.error;
stackTrace = replacement.stackTrace;
} else {
stackTrace ??= AsyncError.defaultStackTrace(error);
}
_addError(error, stackTrace);
}
这个 addError 方法的作用是向流中添加一个错误事件,但在添加之前会进行状态检查:
- 首先,通过调用
_mayAddEvent属性来检查是否可以添加新的事件。_mayAddEvent属性会根据流的状态来确定是否允许添加事件。如果不允许添加事件,将会抛出异常_badEventState()。 - 接着,检查错误事件,并使用
checkNotNullable方法确保error参数不为空。 - 然后,通过调用
Zone.current.errorCallback方法来处理错误事件。这个方法可能会返回一个AsyncError对象,表示对错误事件的替代处理。如果有替代处理,将使用替代处理的错误和堆栈信息。 - 如果没有替代处理,将使用默认的堆栈信息(
AsyncError.defaultStackTrace方法)。 - 最后,调用
_addError(error, stackTrace)方法将错误事件和堆栈信息添加到流中。
总之,这个方法用于向流中添加错误事件,但在添加之前会进行状态检查,确保在合适的时候添加事件,同时处理错误事件的替代处理和堆栈信息。如果不允许添加事件,将抛出异常以指示错误状态。
close(_StreamController对外暴露的close接口)
关闭此控制器并在流上发送一个 "done" 事件。
/// Closes this controller and sends a done event on the stream.
///
/// The first time a controller is closed, a "done" event is added to its
/// stream.
///
/// You are allowed to close the controller more than once, but only the first
/// call has any effect.
///
/// After closing, no further events may be added using [add], [addError]
/// or [addStream].
///
/// The returned future is completed when the done event has been delivered.
Future close() {
if (isClosed) {
return _ensureDoneFuture();
}
if (!_mayAddEvent) throw _badEventState();
_closeUnchecked();
return _ensureDoneFuture();
}
void _closeUnchecked() {
_state |= _STATE_CLOSED;
if (hasListener) {
_sendDone();
} else if (_isInitialState) {
_ensurePendingEvents().add(const _DelayedDone());
}
}
这个 close 方法的作用是关闭流控制器,并在流上发送一个 "done" 事件。它包含以下几个步骤:
- 首先,通过检查
isClosed属性来判断是否已经关闭了控制器。如果已经关闭,直接返回_ensureDoneFuture(),该方法返回一个Future,用于等待 "done" 事件被处理。 - 如果控制器没有关闭,继续执行下面的步骤。首先,通过调用
_mayAddEvent属性来检查是否可以添加新的事件。如果不允许添加事件,将会抛出异常_badEventState()。 - 接着,调用
_closeUnchecked()方法来执行控制器的关闭操作。 - 在
_closeUnchecked()方法中,首先将_state的状态标记为已关闭_STATE_CLOSED,表示控制器已经关闭。 - 然后,通过检查是否有活跃的监听器
hasListener,如果有,则立即调用_sendDone()方法发送 "done" 事件。 - 如果没有活跃的监听器,并且流还处于初始状态
_isInitialState,则需要确保存在一个挂起事件列表,并将 "done" 事件包装成_DelayedDone对象添加到挂起事件列表中。
总之,这个方法用于关闭流控制器,并发送 "done" 事件。只有第一次关闭调用会有实际效果,后续的关闭调用不会产生影响。关闭后,不能再使用 add、addError 或 addStream 添加更多的事件。方法返回一个 Future,用于等待 "done" 事件被处理。
创建订阅对象,在订阅对象内部消费事件(实现_StreamControllerLifeCycle interface)
_subscribe
StreamSubscription<T> _subscribe(void onData(T data)?, Function? onError,
void onDone()?, bool cancelOnError) {
if (!_isInitialState) {
throw StateError("Stream has already been listened to.");
}
_ControllerSubscription<T> subscription = _ControllerSubscription<T>(
this, onData, onError, onDone, cancelOnError);
_PendingEvents<T>? pendingEvents = _pendingEvents;
_state |= _STATE_SUBSCRIBED;
if (_isAddingStream) {
_StreamControllerAddStreamState<T> addState = _varData as dynamic;
addState.varData = subscription;
addState.resume();
} else {
_varData = subscription;
}
subscription._setPendingEvents(pendingEvents);
subscription._guardCallback(() {
_runGuarded(onListen);
});
return subscription;
}
这段代码是 Dart 中与 StreamController 相关的一部分,用于创建一个 StreamSubscription 对象并将其与一个 Stream 相关联,以便监听该 Stream 上的事件。
-
StreamSubscription<T> _subscribe(...)方法用于订阅一个Stream。它接受以下参数:onData(T data)?:当有新数据可用时的回调函数。onError:当出现错误时的回调函数。onDone():当Stream完成时的回调函数。cancelOnError:一个布尔值,指示是否在遇到错误时自动取消订阅。
-
首先,它检查
_isInitialState变量,以确保Stream还没有被监听。如果已经被监听过,会抛出一个StateError。 -
接下来,它创建一个
_ControllerSubscription<T>对象,这是StreamSubscription的一个实现,用于管理订阅。 -
然后,它设置
_varData为这个订阅对象,标记_STATE_SUBSCRIBED为已订阅状态。 -
如果当前正在添加一个
Stream(这可能是通过StreamController.addStream方法添加的),则将订阅对象存储在addState.varData中,并恢复添加流的操作。 -
否则,直接将订阅对象存储在
_varData中。 -
最后,它设置订阅对象的挂起事件
_setPendingEvents,并在订阅对象上调用_guardCallback,以确保在订阅过程中捕获任何异常。
总之,这段代码的作用是创建一个 StreamSubscription 对象,并将其与 Stream 关联起来,以便监听事件,并根据需要处理数据、错误和完成事件。
_recordCancel
Future<void>? _recordCancel(StreamSubscription<T> subscription) {
// When we cancel, we first cancel any stream being added,
// Then we call `onCancel`, and finally the _doneFuture is completed.
// If either of addStream's cancel or `onCancel` returns a future,
// we wait for it before continuing.
// Any error during this process ends up in the returned future.
// If more errors happen, we act as if it happens inside nested try/finally
// blocks or whenComplete calls, and only the last error ends up in the
// returned future.
Future<void>? result;
if (_isAddingStream) {
_StreamControllerAddStreamState<T> addState = _varData as dynamic;
result = addState.cancel();
}
_varData = null;
_state =
(_state & ~(_STATE_SUBSCRIBED | _STATE_ADDSTREAM)) | _STATE_CANCELED;
var onCancel = this.onCancel;
if (onCancel != null) {
if (result == null) {
// Only introduce a future if one is needed.
// If _onCancel returns null, no future is needed.
try {
var cancelResult = onCancel();
if (cancelResult is Future<void>) {
result = cancelResult;
}
} catch (e, s) {
// Return the error in the returned future.
// Complete it asynchronously, so there is time for a listener
// to handle the error.
result = _Future().._asyncCompleteError(e, s);
}
} else {
// Simpler case when we already know that we will return a future.
result = result.whenComplete(onCancel);
}
}
void complete() {
var doneFuture = _doneFuture;
if (doneFuture != null && doneFuture._mayComplete) {
doneFuture._asyncComplete(null);
}
}
if (result != null) {
result = result.whenComplete(complete);
} else {
complete();
}
return result;
}
这段代码是 Dart 中与 StreamController 相关的一部分,用于处理取消订阅操作,并确保在取消订阅时正确处理所有可能的异步事件。
-
Future<void>? _recordCancel(StreamSubscription<T> subscription)方法用于记录取消订阅操作。它接受一个StreamSubscription对象,表示要取消的订阅。 -
首先,它检查是否正在添加一个
Stream(通过_isAddingStream变量),如果是,则调用_StreamControllerAddStreamState<T>的cancel()方法来取消添加流的操作,并将结果存储在result变量中。 -
接着,它将
_varData设置为null,表示取消了订阅,并更新_state变量,将_STATE_SUBSCRIBED、_STATE_ADDSTREAM和_STATE_CANCELED标志设置为相应的值。 -
然后,它获取
onCancel回调函数。如果存在onCancel回调函数,它会执行以下步骤:- 如果
result为null,则表示还没有返回一个Future,会调用onCancel函数,并检查它的返回值是否为Future<void>类型。如果是,则将返回值存储在result中。 - 如果
result不为null,表示已经返回了一个Future,它会将onCancel函数添加到result的whenComplete链中,以便在result完成时执行onCancel。
- 如果
-
接下来,它定义了一个名为
complete的函数,用于在完成时触发_doneFuture(表示Stream完成的Future)。 -
如果
result不为null,则将complete函数添加到result的whenComplete链中,以确保在result完成时调用complete。 -
最后,它检查
_doneFuture是否存在且可以完成(_mayComplete为true),如果是,则调用_doneFuture的_asyncComplete(null)方法来完成_doneFuture。
总之,这段代码的作用是处理取消订阅操作,包括取消添加流操作、执行 onCancel 回调函数以及完成 _doneFuture,并确保所有这些操作都正确处理了异步事件。
_recordPause
void _recordPause(StreamSubscription<T> subscription) {
if (_isAddingStream) {
_StreamControllerAddStreamState<T> addState = _varData as dynamic;
addState.pause();
}
_runGuarded(onPause);
}
这段代码是 Dart 中与 StreamController 相关的一部分,用于记录暂停订阅操作,并在暂停时执行一些额外的逻辑。
让我解释一下这段代码的关键部分:
void _recordPause(StreamSubscription<T> subscription)方法用于记录暂停订阅操作。它接受一个StreamSubscription对象,表示要暂停的订阅。- 首先,它检查是否正在添加一个
Stream(通过_isAddingStream变量),如果是,则调用_StreamControllerAddStreamState<T>的pause()方法来暂停添加流的操作。 - 接着,它调用
_runGuarded(onPause),这表示在暂停订阅时会执行onPause回调函数。
总之,这段代码的作用是记录暂停订阅操作,并在暂停时执行额外的逻辑,包括暂停添加流的操作和执行 onPause 回调函数。
_recordResume
void _recordResume(StreamSubscription<T> subscription) {
if (_isAddingStream) {
_StreamControllerAddStreamState<T> addState = _varData as dynamic;
addState.resume();
}
_runGuarded(onResume);
}
这段代码是 Dart 中与 StreamController 相关的一部分,用于记录恢复订阅操作,并在恢复时执行一些额外的逻辑。
让我解释一下这段代码的关键部分:
void _recordResume(StreamSubscription<T> subscription)方法用于记录恢复订阅操作。它接受一个StreamSubscription对象,表示要恢复的订阅。- 首先,它检查是否正在添加一个
Stream(通过_isAddingStream变量),如果是,则调用_StreamControllerAddStreamState<T>的resume()方法来恢复添加流的操作。 - 接着,它调用
_runGuarded(onResume),这表示在恢复订阅时会执行onResume回调函数。
总之,这段代码的作用是记录恢复订阅操作。
_ControllerSubscription(_BufferingStreamSubscription、StreamSubscription)对象消费事件
-
_ControllerSubscription<T> subscription = _ControllerSubscription<T>( this, onData, onError, onDone, cancelOnError);订阅对象创建。 -
会调用
subscription._setPendingEvents(pendingEvents);将事件挂起。
_setPendingEvents
/// Sets the subscription's pending events object.
///
/// This can only be done once. The pending events object is used for the
/// rest of the subscription's life cycle.
void _setPendingEvents(_PendingEvents<T>? pendingEvents) {
assert(_pending == null);
if (pendingEvents == null) return;
_pending = pendingEvents;
if (!pendingEvents.isEmpty) {
_state |= _STATE_HAS_PENDING;
pendingEvents.schedule(this);
}
}
这段代码是用来设置订阅的待处理事件对象(pending events object)的。以下是它的主要作用:
_setPendingEvents(_PendingEvents<T>? pendingEvents)方法用于设置订阅的待处理事件对象。这个对象在订阅的生命周期中将被用到。- 在设置之前,首先使用
assert断言确保_pending属性为null,以确保只能设置一次。 - 如果传入的
pendingEvents参数为null,则不执行任何操作,直接返回。 - 如果
pendingEvents参数不为null,则将_pending属性设置为传入的pendingEvents,表示该订阅将使用这个待处理事件对象。 - 如果
pendingEvents不为空(即其中包含待处理的事件),则将_state属性的_STATE_HAS_PENDING位设置为1,表示订阅有待处理的事件。然后,通过pendingEvents.schedule(this)将待处理事件调度,以便后续处理。
总之,这段代码的主要作用是设置订阅的待处理事件对象,并在设置之后将待处理事件调度以进行后续处理。
真正调度事件的是_PendingEvents类
_PendingEvents(调度事件)
/// Container and manager of pending events for a stream subscription.
class _PendingEvents<T> {}
_PendingEvents<T> 是一个用于管理流订阅中待处理事件的容器和管理器。它用于存储那些尚未被处理的事件,以便在适当的时候执行这些事件。通常,这个类会被用于处理流订阅中的异步事件,以确保它们按顺序和正确地被触发。
这个类的实现通常包括以下功能:
- 存储待处理的事件:它会保存那些已经产生但还没有被订阅者处理的事件。
- 事件调度:它会负责将待处理的事件按照一定的规则或策略进行调度,以便后续执行。
- 事件处理:它会在合适的时候执行待处理的事件,通常会根据一些条件或触发时机来执行这些事件。
- 事件清理:一旦事件被成功处理,它会负责将这些事件从待处理队列中移除,以释放资源。
// No async event has been scheduled.
static const int stateUnscheduled = 0;
// An async event has been scheduled to run a function.
static const int stateScheduled = 1;
// An async event has been scheduled, but it will do nothing when it runs.
// Async events can't be preempted.
static const int stateCanceled = 3;
/// State of being scheduled.
///
/// Set to [stateScheduled] when pending events are scheduled for
/// async dispatch. Since we can't cancel a [scheduleMicrotask] call, if
/// scheduling is "canceled", the _state is simply set to [stateCanceled]
/// which will make the async code do nothing except resetting [_state].
///
/// If events are scheduled while the state is [stateCanceled], it is
/// merely switched back to [stateScheduled], but no new call to
/// [scheduleMicrotask] is performed.
int _state = stateUnscheduled;
/// First element in the list of pending events, if any.
_DelayedEvent? firstPendingEvent;
/// Last element in the list of pending events. New events are added after it.
_DelayedEvent? lastPendingEvent;
bool get isScheduled => _state == stateScheduled;
bool get _eventScheduled => _state >= stateScheduled;
这段代码是在定义一个类,其中包含了一些状态常量和实例变量,用于管理异步事件的调度和执行。以下是对其中一些重要部分的解释:
-
_state是一个整数,用于表示调度状态。它有三个可能的值:stateUnscheduled(0): 表示尚未安排异步事件。stateScheduled(1): 表示已经安排了异步事件以执行某个函数。stateCanceled(3): 表示已经安排了异步事件,但在运行时将不执行任何操作。这通常用于取消异步事件的执行。
-
firstPendingEvent和lastPendingEvent是指向待处理事件链表的指针。这些事件通常按顺序排列在链表中,新事件会添加到链表的末尾。 -
isScheduled是一个布尔值,用于检查当前是否已安排异步事件执行。 -
_eventScheduled是一个内部布尔值,用于表示是否有异步事件已经被安排。
这段代码的目的是创建一个管理异步事件调度和执行的机制,以便在合适的时机执行已安排的事件函数。通常,它会在异步代码中使用,以确保事件按照正确的顺序和时间执行。
schedule
/// Schedule an event to run later.
///
/// If called more than once, it should be called with the same dispatch as
/// argument each time. It may reuse an earlier argument in some cases.
void schedule(_EventDispatch<T> dispatch) {
if (isScheduled) return;
assert(!isEmpty);
if (_eventScheduled) {
assert(_state == stateCanceled);
_state = stateScheduled;
return;
}
scheduleMicrotask(() {
int oldState = _state;
_state = stateUnscheduled;
if (oldState == stateCanceled) return;
handleNext(dispatch);
});
_state = stateScheduled;
}
这段代码是用于调度事件以在稍后执行的方法。以下是代码的关键部分解释:
schedule方法用于将事件安排在稍后执行。它接受一个_EventDispatch<T>类型的参数dispatch,表示要执行的事件函数。- 在方法内部首先检查当前是否已经有事件被安排,如果已经有了,则不执行任何操作,以避免重复安排。
- 如果之前有事件被安排但被取消(
stateCanceled),则将其状态重新设置为stateScheduled并返回,表示重新安排事件执行。 - 如果没有事件被安排或之前的事件已经执行完毕,它会使用
scheduleMicrotask函数来将事件函数异步地加入到微任务队列中以在稍后执行。 - 最后,将状态
_state设置为stateScheduled,表示事件已经成功安排。
总之,这段代码的目的是确保事件按照正确的顺序和时间执行,并避免重复安排相同的事件。它使用了 Dart 中的 scheduleMicrotask 函数来异步执行事件函数。
cancelSchedule
void cancelSchedule() {
if (isScheduled) _state = stateCanceled;
}
这段代码定义了一个名为 cancelSchedule 的方法。以下是代码的解释:
cancelSchedule方法用于取消之前安排的事件。它首先检查当前是否已经有事件被安排,如果已经有了,则将状态_state设置为stateCanceled,表示事件被取消。- 如果没有事件被安排或之前的事件已经执行完毕,方法不会执行任何操作。
总之,这段代码的作用是提供一个机制来取消之前安排的事件,以确保它不会在稍后执行。取消事件后,如果需要再次执行相同的事件,需要重新安排。
add
void add(_DelayedEvent event) {
var lastEvent = lastPendingEvent;
if (lastEvent == null) {
firstPendingEvent = lastPendingEvent = event;
} else {
lastPendingEvent = lastEvent.next = event;
}
}
这段代码定义了一个 add 方法,它的作用是向一个事件队列中添加一个延迟事件 _DelayedEvent。
具体解释如下:
add方法接受一个_DelayedEvent类型的参数event,表示要添加的延迟事件。- 首先,方法检查队列中是否已经存在事件。如果队列为空(即
lastPendingEvent为null),则将event赋值给firstPendingEvent和lastPendingEvent,表示这是队列中唯一的事件。 - 如果队列不为空,说明已经有事件存在,那么将
event添加到队列的末尾,也就是将lastEvent的next设置为event,并更新lastPendingEvent为event,以保持队列的完整性。
这段代码的作用是将延迟事件添加到队列中,以便稍后按顺序执行这些事件。
isEmpty
bool get isEmpty => lastPendingEvent == null;
这行代码定义了一个名为 isEmpty 的 getter 方法,用于检查事件队列是否为空。它通过判断 lastPendingEvent 是否为 null 来确定队列是否为空。
如果 lastPendingEvent 为 null,意味着队列中没有任何事件,那么 isEmpty 返回 true,表示队列为空;否则,如果队列中有至少一个事件,isEmpty 返回 false,表示队列不为空。
这个方法通常用于在处理事件队列时检查是否还有待处理的事件,以便确定是否继续执行事件处理的逻辑。
handleNext
void handleNext(_EventDispatch<T> dispatch) {
assert(!isScheduled);
assert(!isEmpty);
_DelayedEvent event = firstPendingEvent!;
_DelayedEvent? nextEvent = event.next;
firstPendingEvent = nextEvent;
if (nextEvent == null) {
lastPendingEvent = null;
}
event.perform(dispatch);
}
这段代码定义了一个 handleNext 方法,用于处理事件队列中的下一个事件。以下是该方法的功能:
-
首先,它断言了两个条件:
isScheduled必须为false,表示当前没有其他事件在执行。isEmpty必须为false,表示事件队列不为空。
-
然后,它获取事件队列中的第一个事件
event,并检查是否存在下一个事件nextEvent。 -
如果存在下一个事件
nextEvent,则将firstPendingEvent指向下一个事件,表示从队列中移除了第一个事件,并且更新lastPendingEvent为null,如果队列中只有一个事件的话。 -
最后,它调用
event.perform(dispatch)方法,执行事件的处理操作,将事件传递给dispatch处理器来执行。
总之,这个方法用于处理事件队列中的下一个事件,并确保在处理前检查了必要的条件。
clear
void clear() {
if (isScheduled) cancelSchedule();
firstPendingEvent = lastPendingEvent = null;
}
这段代码定义了一个 clear 方法,用于清空事件队列。以下是该方法的功能:
- 首先,它检查是否已经有事件被调度,如果有,则调用
cancelSchedule()方法取消已经调度的事件。 - 然后,它将
firstPendingEvent和lastPendingEvent都设置为null,表示事件队列为空。
这个方法的作用是在不需要处理事件队列中的任何事件时,将事件队列清空,确保没有事件留在队列中。
_DelayedEvent
/// A delayed event on a buffering stream subscription.
abstract class _DelayedEvent<T> {
/// Added as a linked list on the [StreamController].
_DelayedEvent? next;
/// Execute the delayed event on the [StreamController].
void perform(_EventDispatch<T> dispatch);
}
_DelayedData
/// A delayed data event.
class _DelayedData<T> extends _DelayedEvent<T> {
final T value;
_DelayedData(this.value);
void perform(_EventDispatch<T> dispatch) {
dispatch._sendData(value);
}
}
事件输出(_SyncStreamControllerDispatch、_AsyncStreamControllerDispatch)
mixin _SyncStreamControllerDispatch<T>
implements _StreamController<T>, SynchronousStreamController<T> {
void _sendData(T data) {
_subscription._add(data);
}
void _sendError(Object error, StackTrace stackTrace) {
_subscription._addError(error, stackTrace);
}
void _sendDone() {
_subscription._close();
}
}
这段代码定义了一个 mixin _SyncStreamControllerDispatch<T>,该 mixin 实现了 _StreamController<T> 和 SynchronousStreamController<T> 接口,并包含了以下三个方法:
_sendData(T data): 用于将数据发送给订阅者,即调用_subscription._add(data)来通知订阅者新的数据已经产生。_sendError(Object error, StackTrace stackTrace): 用于发送错误信息给订阅者,即调用_subscription._addError(error, stackTrace)来通知订阅者发生了错误。_sendDone(): 用于发送流的完成信号给订阅者,即调用_subscription._close()来通知订阅者流已经完成。
这些方法用于在 StreamController 中处理数据、错误和完成事件,确保这些事件正确地发送给订阅者。
mixin _AsyncStreamControllerDispatch<T> implements _StreamController<T> {
void _sendData(T data) {
_subscription._addPending(_DelayedData<T>(data));
}
void _sendError(Object error, StackTrace stackTrace) {
_subscription._addPending(_DelayedError(error, stackTrace));
}
void _sendDone() {
_subscription._addPending(const _DelayedDone());
}
}
这段代码定义了一个 mixin _AsyncStreamControllerDispatch<T>,它实现了 _StreamController<T> 接口,并包含了以下三个方法:
_sendData(T data): 用于将数据发送给订阅者。它通过调用_subscription._addPending(_DelayedData<T>(data))来将数据添加到待处理的事件队列中。_sendError(Object error, StackTrace stackTrace): 用于发送错误信息给订阅者。它通过调用_subscription._addPending(_DelayedError(error, stackTrace))来将错误事件添加到待处理的事件队列中。_sendDone(): 用于发送流的完成信号给订阅者。它通过调用_subscription._addPending(const _DelayedDone())来将完成事件添加到待处理的事件队列中。
这些方法用于在 StreamController 中异步处理数据、错误和完成事件,确保这些事件被安排在事件队列中以便后续异步处理。