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

基本概念

Flutter 中的 Stream(流)是一个用于异步事件处理的重要概念,它允许你在应用程序中传递和监听数据的变化。Stream 通常与 StreamController 一起使用,StreamController 用于管理流的数据并将数据推送给监听者。

Sink

csharp 复制代码
/// A generic destination for data.
///
/// Multiple data values can be put into a sink, and when no more data is
/// available, the sink should be closed.
///
/// This is a generic interface that other data receivers can implement.
abstract class Sink<T> {}

根据官方文档解释:

  • 抽象类 Sink<T> 表示一个数据接收器,用于接收泛型类型 T 的数据。
  • 抽象类是不能被直接实例化的,而是需要被其他类继承或实现。

add

csharp 复制代码
abstract class Sink<T> {
  /// Adds [data] to the sink.
  ///
  /// Must not be called after a call to [close].
  void add(T data);
}

这是一个抽象方法,用于将数据添加到接收器中。开发者需要在实现这个接口时提供方法的具体实现。它要求传入一个类型为 T 的数据,将其添加到接收器中。

close

csharp 复制代码
abstract class Sink<T> {
  /// Closes the sink.
  ///
  /// The [add] method must not be called after this method.
  ///
  /// Calling this method more than once is allowed, but does nothing.
  void close();
}

这是另一个抽象方法,用于关闭接收器。关闭接收器表示不再接受新的数据。与 add 方法一样,开发者需要在实现时提供具体的关闭逻辑。同时,根据接收器的实现,可能允许多次调用 close 方法,但多次调用什么也不做。

EventSink

csharp 复制代码
/// A [Sink] that supports adding errors.
///
/// This makes it suitable for capturing the results of asynchronous
/// computations, which can complete with a value or an error.
///
/// The [EventSink] has been designed to handle asynchronous events from
/// [Stream]s. See, for example, [Stream.eventTransformed] which uses
/// `EventSink`s to transform events.
abstract class EventSink<T> implements Sink<T> {}

EventSink 是一个抽象类,它实现了 Sink<T> 接口,表示它是一个数据接收器。它用于处理异步计算的结果,这些计算可能产生值或错误。它通过泛型参数 T 来指定可以接收的数据类型,与前面提到的 Sink<T> 相似。

EventSink<T> 是一个用于处理异步事件的接口,它可以接收数据事件和错误事件,并提供关闭接收器的方法。这种设计非常适用于处理异步计算的结果,例如处理来自 Stream 的异步事件。

add

csharp 复制代码
abstract class EventSink<T> implements Sink<T> {
  /// Adds a data [event] to the sink.
  ///
  /// Must not be called on a closed sink.
  void add(T event);
}

这是一个方法,用于向接收器添加数据事件 event。与普通的 Sink 接口相同,它要求传入类型为 T 的数据事件,并将其添加到接收器中。但是,请注意,这里使用了术语 "event" 而不是 "data",因为这个接口主要用于处理异步事件。

addError

csharp 复制代码
abstract class EventSink<T> implements Sink<T> {
  /// Adds an [error] to the sink.
  ///
  /// Must not be called on a closed sink.
  void addError(Object error, [StackTrace? stackTrace]);
}

这是另一个方法,用于向接收器添加错误信息。它允许你将一个错误对象 error 添加到接收器中,还可以选择性地传递与错误相关的堆栈信息 stackTrace。这对于捕获异步计算的错误非常有用。

close

csharp 复制代码
abstract class EventSink<T> implements Sink<T> {
  /// Closes the sink.
  ///
  /// Calling this method more than once is allowed, but does nothing.
  ///
  /// Neither [add] nor [addError] must be called after this method.
  void close();
}

与普通的 Sink 接口一样,这个方法用于关闭接收器,表示不再接受新的数据。与之前提到的 Sink 不同的是,它还可以处理错误事件。

StreamSink

csharp 复制代码
/// A object that accepts stream events both synchronously and asynchronously.
///
/// A [StreamSink] combines the methods from [StreamConsumer] and [EventSink].
///
/// The [EventSink] methods can't be used while the [addStream] is called.
/// As soon as the [addStream]'s [Future] completes with a value, the
/// [EventSink] methods can be used again.
///
/// If [addStream] is called after any of the [EventSink] methods, it'll
/// be delayed until the underlying system has consumed the data added by the
/// [EventSink] methods.
///
/// When [EventSink] methods are used, the [done] [Future] can be used to
/// catch any errors.
///
/// When [close] is called, it will return the [done] [Future].
abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {}
  • 定义了一个抽象类 StreamSink<S>,它表示一个对象,可以同时接收同步和异步的流事件
  • StreamSink 组合了 StreamConsumerEventSink 的方法。
  • 它提供了关闭接收器和处理完成的功能。这对于处理数据流非常有用。
  • 异步和同步事件的处理:StreamSink 允许你同时处理同步事件和异步事件。EventSink 方法在调用 addStream 方法期间无法使用,但一旦 addStream 方法的 Future 完成并返回,就可以再次使用这些方法。

close

csharp 复制代码
abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {
  /// Tells the stream sink that no further streams will be added.
  ///
  /// This allows the stream sink to complete any remaining work and release
  /// resources that are no longer needed
  ///
  /// Returns a future which is completed when the stream sink has shut down.
  /// If cleaning up can fail, the error may be reported in the returned future,
  /// otherwise it completes with `null`.
  ///
  /// Returns the same future as [done].
  ///
  /// The stream sink may close before the [close] method is called, either due
  /// to an error or because it is itself providing events to someone who has
  /// stopped listening. In that case, the [done] future is completed first,
  /// and the `close` method will return the `done` future when called.
  ///
  /// Unifies [StreamConsumer.close] and [EventSink.close] which both mark their
  /// object as not expecting any further events.
  Future close();
}

这是一个方法,用于告诉流事件接收器,不会再添加更多的流。这允许流事件接收器完成任何剩余的工作并释放不再需要的资源。该方法返回一个 Future,该 Future 在流事件接收器关闭时完成。如果关闭过程中发生错误,错误可能会在返回的 Future 中报告。

done

csharp 复制代码
abstract class StreamSink<S> implements EventSink<S>, StreamConsumer<S> {

  /// Return a future which is completed when the [StreamSink] is finished.
  ///
  /// If the `StreamSink` fails with an error,
  /// perhaps in response to adding events using [add], [addError] or [close],
  /// the [done] future will complete with that error.
  ///
  /// Otherwise, the returned future will complete when either:
  ///
  /// * all events have been processed and the sink has been closed, or
  /// * the sink has otherwise been stopped from handling more events
  ///   (for example by canceling a stream subscription).
  Future get done;
}

这是一个属性,它返回一个 Future,该 Future 在流事件接收器完成时完成。如果流事件接收器失败并导致错误(例如通过 addaddErrorclose 添加事件时出错),则 doneFuture 将以该错误完成。否则,doneFuture 将在以下情况之一完成:

  • 所有事件都已处理并且接收器已关闭。
  • 接收器已停止处理更多事件(例如,取消了流订阅)。

StreamController

csharp 复制代码
abstract class StreamController<T> implements StreamSink<T> {}

定义了一个抽象类,表示一个数据流控制器。它通过泛型参数 T 来指定可以处理的事件的类型。这个控制器允许向它的 stream 发送数据、错误和完成事件。

总结

他们从SinkStreamSink都只是到导入接口,并无直接继承关系,在抽象类方面按照功能解耦,最终由StreamController整合,负责添加的是StreamControlelr,负责监听的是Stream,最终在当前的Zone中执行回调Zone.runUnaryGuarded()Zone类似一个沙盒环境,在APP启动的时候创建。

相关推荐
大圣编程5 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang5 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆6 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜6 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞8 小时前
异步HttpModule的实现方式
java·服务器·前端
丹宇码农10 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器
2501_9437823510 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统
GV191rLvq10 小时前
基于Socket实现的最简单的Web服务器【ASP.NET原理分析】
服务器·前端·asp.net
吠品11 小时前
LangChain 里 tool_call_id 为空?一次 MCP 工具集成的排查记录
前端