Flutter中的Stream详解

387 阅读2分钟

在 Flutter 中,响应式编程是一种重要的设计理念,而 Stream 是实现异步数据流和响应式UI更新的关键工具。本文将深入剖析 Flutter 中的 Stream,带你了解它的本质、单播和多播的区别,以及如何使用 StreamBuilder 和 StreamController 来构建流式响应式应用。

什么是 Stream?

Stream 是 Dart 语言提供的一种异步数据序列,可以理解为数据的“时间轴”,它会随着时间推移不断发出数据事件。Flutter 和 Dart 生态中,Stream 广泛用于处理网络请求、用户输入、事件监听等场景。

Stream 中的数据是按顺序依次到达的,这使得我们可以优雅地处理异步数据流。

单播(Single-subscription)与多播(Broadcast)Stream

单播 Stream

单播流只能有一个监听者(listener),也就是说,只能被一个订阅者订阅:

  • 适用于一次性任务,如网络请求结果、单次事件处理。
  • 当有多个订阅者尝试监听同一个单播流时,会抛出异常。
Stream<int> singleStream = Stream.fromIterable([1, 2, 3]);

singleStream.listen((value) {
  print('Listener 1: $value');
});

// 如果再添加另一个监听,会报错
// singleStream.listen((value) => print('Listener 2: $value')); // 报错!

多播(Broadcast)Stream

多播流允许多个监听者同时订阅。它更适合广播事件,比如 UI 事件、传感器数据等。

通过调用 asBroadcastStream(),可以将单播流转换成多播流:

Stream<int> broadcastStream = Stream.fromIterable([1, 2, 3]).asBroadcastStream();

broadcastStream.listen((value) {
  print('Listener 1: $value');
});

broadcastStream.listen((value) {
  print('Listener 2: $value');
});

或者直接创建多播流:

StreamController<int> controller = StreamController<int>.broadcast();

StreamController:主动控制数据流

StreamController 是用来创建和控制 Stream 的核心类,它允许我们手动添加数据、错误或关闭事件到流中。它是连接数据生产者和消费者的桥梁。

创建 StreamController

final controller = StreamController<int>();

// 监听数据
controller.stream.listen((data) {
  print('Received: $data');
});

// 添加数据
controller.sink.add(1);
controller.sink.add(2);

// 关闭流
controller.close();

Broadcast Controller

如果希望流支持多个监听者,需创建广播类型的控制器:

final broadcastController = StreamController<int>.broadcast();

broadcastController.stream.listen((data) => print('Listener 1: $data'));
broadcastController.stream.listen((data) => print('Listener 2: $data'));

broadcastController.sink.add(10);
broadcastController.sink.add(20);

broadcastController.close();

StreamBuilder:Flutter 中的流式UI构建器

StreamBuilder 是 Flutter 框架中专门用来监听 Stream 并根据流数据动态构建 UI 的 Widget。它使得响应式编程变得简单直观。

基本用法

Stream<int> numberStream = Stream.periodic(Duration(seconds: 1), (count) => count).take(10);

StreamBuilder<int>(
  stream: numberStream,
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    } else if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    } else if (snapshot.hasData) {
      return Text('Current number: ${snapshot.data}');
    } else {
      return Text('Stream ended');
    }
  },
)

重要属性

  • stream:要监听的 Stream。
  • builder:每当流发出新事件时调用,用于构建 Widget。
  • snapshot:包含当前流的状态和最新数据。

常见使用场景

  • 网络数据加载和刷新
  • 实时计时器或动画
  • 用户输入事件监听
  • 传感器数据显示

总结

组件功能特点和注意点
Stream异步数据流单播(默认)、多播(广播)
StreamController手动创建和管理流支持广播类型,添加数据、错误,控制流的生命周期
StreamBuilder响应流数据,构建UI绑定流和UI,自动监听流变化,简化响应式UI开发

Flutter 中的 Stream 机制为异步数据处理和响应式编程提供了强大的支持,理解并灵活使用单播、多播流,结合 StreamController 和 StreamBuilder,可以极大地提升你的应用性能和用户体验。