StreamController(同步流、异步流)
/// A controller with a [stream] that supports only one single subscriber.
///
/// If [sync] is true, the returned stream controller is a
/// [SynchronousStreamController], and must be used with the care
/// and attention necessary to not break the [Stream] contract. If in doubt,
/// use the non-sync version.
///
/// Using an asynchronous controller will never give the wrong
/// behavior, but using a synchronous controller incorrectly can cause
/// otherwise correct programs to break.
///
/// A synchronous controller is only intended for optimizing event
/// propagation when one asynchronous event immediately triggers another.
/// It should not be used unless the calls to [add] or [addError]
/// are guaranteed to occur in places where it won't break `Stream` invariants.
///
/// Use synchronous controllers only to forward (potentially transformed)
/// events from another stream or a future.
///
/// A Stream should be inert until a subscriber starts listening on it (using
/// the [onListen] callback to start producing events). Streams should not
/// leak resources (like websockets) when no user ever listens on the stream.
///
/// The controller buffers all incoming events until a subscriber is
/// registered, but this feature should only be used in rare circumstances.
///
/// The [onPause] function is called when the stream becomes
/// paused. [onResume] is called when the stream resumed.
///
/// The [onListen] callback is called when the stream
/// receives its listener and [onCancel] when the listener ends
/// its subscription. If [onCancel] needs to perform an asynchronous operation,
/// [onCancel] should return a future that completes when the cancel operation
/// is done.
///
/// If the stream is canceled before the controller needs data the
/// [onResume] call might not be executed.
factory StreamController(
{void onListen()?,
void onPause()?,
void onResume()?,
FutureOr<void> onCancel()?,
bool sync = false}) {
return sync
? _SyncStreamController<T>(onListen, onPause, onResume, onCancel)
: _AsyncStreamController<T>(onListen, onPause, onResume, onCancel);
}
- 一个带有 [stream] 的控制器,仅支持单个订阅者。
- 如果 [sync] 为 true,返回的流控制器是一个 [SynchronousStreamController],必须小心谨慎地使用,以确保不破坏 [Stream] 契约。如果有疑虑,应使用非同步版本。
- 使用异步控制器永远不会导致错误行为,但不正确地使用同步控制器可能会导致 其他正确的程序出现问题。
- 同步控制器仅用于在一个异步事件立即触发另一个事件的情况下优化事件传播。
- 除非可以确保 [add] 或 [addError] 调用发生在不会破坏
Stream不变式的地方,否则不应使用同步控制器。 - 只有在将(可能经过转换)事件从另一个流或 Future 转发时,才应使用同步控制器。
- 直到有订阅者开始监听流(使用 [onListen] 回调来开始生成事件)之前,流应该是不活动的。流不应在没有用户监听流的情况下泄露资源(例如 WebSockets)。
- 控制器会缓冲所有传入的事件,直到注册订阅者,但这个功能只应在极少数情况下使用。
- 当流暂停时,[onPause] 函数将被调用。当流恢复时,[onResume] 将被调用。
- 当流接收到其监听器时,将调用 [onListen] 回调,并在监听器结束其订阅时调用 [onCancel]。
- 如果 [onCancel] 需要执行异步操作,[onCancel] 应该返回一个在取消操作完成时完成的 future。
- 如果流在控制器需要数据之前被取消,[onResume] 调用可能不会执行。
- [sync]:是否创建同步控制器,默认为 false。
_SyncStreamController
class _SyncStreamController<T> = _StreamController<T>
with _SyncStreamControllerDispatch<T>;
从上面的代码可以看出, 它创建了一个 _SyncStreamController<T> 类,它实际上是 _StreamController<T> 类与 _SyncStreamControllerDispatch<T> 类的组合。通过这种方式,_SyncStreamController 继承了 _StreamController 类的功能,并混合了 _SyncStreamControllerDispatch 类的功能,从而扩展了自己的行为。
通常情况下,这种 mixin 的使用方式允许你将一些通用功能添加到一个类中,而不需要继承多个类或创建多个类的实例。这种方式可以提高代码的可维护性和重用性。在这里,_SyncStreamController 通过混合 _SyncStreamControllerDispatch 来实现同步流控制器的特定功能。
因为同步流控制器和异步流控制器都继承自_StreamController控制器, 所以接下来,我们去到_StreamController源码一探究竟。
_AsyncStreamController
class _AsyncStreamController<T> = _StreamController<T>
with _AsyncStreamControllerDispatch<T>;
这段代码定义了一个 _AsyncStreamController 类,它继承自 _StreamController<T> 类并混入了 _AsyncStreamControllerDispatch<T> 类。
这段代码使用 Dart 中的 mixin 语法,将 _AsyncStreamControllerDispatch<T> 类的功能混入到 _StreamController<T> 类中,从而创建了一个新的 _AsyncStreamController 类。这个新类继承了 _StreamController 类的所有成员,并添加了 _AsyncStreamControllerDispatch 类中定义的功能。
通常情况下,这种方式用于在不改变类的继承关系的情况下,为类添加额外的行为和功能。在这里,_AsyncStreamController 类基本上是 _StreamController 类的增强版本,它包含了额外的异步流控制功能,由 _AsyncStreamControllerDispatch 类提供。这样可以更灵活地扩展和定制类的功能。