Streams 在 Flutter 里的概念
在 Flutter 中,Streams 是一种异步编程模型,用于处理异步数据流。Streams 可以看作是数据的管道,通过它你可以监听到数据的变化并作出相应的处理。它们在处理连续的数据事件(如用户输入、网络请求、实时数据更新等)时非常有用。
两种主要类型的 Streams
-
单订阅流(Single-subscription Stream):
- 这种类型的 Stream 只能被一个监听器(listener)订阅。它适用于那些一次性数据事件流,如文件读取、网络请求等。
- 例子:读取文件数据、HTTP 请求响应等。
-
广播流(Broadcast Stream):
- 这种类型的 Stream 可以被多个监听器同时订阅。它适用于那些持续性数据事件流,如实时更新、传感器数据等。
- 例子:实时数据更新(如股票行情)、传感器数据等。
使用场景
Streams 在以下几种场景中非常有用:
-
用户输入处理:
- 当用户在输入框中输入数据时,你可以使用 Stream 监听输入事件并实时处理数据。
-
网络请求:
- 当你需要处理来自服务器的连续数据(如实时聊天信息、推送通知等)时,Streams 是一个很好的选择。
-
实时数据更新:
- 对于需要实时更新的数据,如股票行情、天气信息等,使用 Stream 可以方便地监听和处理数据变化。
-
传感器数据:
- 处理来自设备传感器的连续数据,如加速度计、陀螺仪等。
-
事件总线:
- 使用广播流(Broadcast Stream)可以实现事件总线模式,在应用程序中发布和订阅各种事件。
示例代码
单订阅流示例
import 'dart:async';
void main() {
// 创建一个单订阅流控制器
final StreamController<int> controller = StreamController<int>();
// 监听流
controller.stream.listen((data) {
print('Received: $data');
});
// 添加数据到流
controller.add(1);
controller.add(2);
controller.add(3);
// 关闭流
controller.close();
}
广播流示例
import 'dart:async';
void main() {
// 创建一个广播流控制器
final StreamController<int> controller = StreamController<int>.broadcast();
// 监听流
controller.stream.listen((data) {
print('Listener 1: Received: $data');
});
controller.stream.listen((data) {
print('Listener 2: Received: $data');
});
// 添加数据到流
controller.add(1);
controller.add(2);
controller.add(3);
// 关闭流
controller.close();
}
在 Flutter 中使用 Streams
在 Flutter 中,Streams 常与 StreamBuilder
小部件一起使用,以便在构建 UI 时监听和响应数据变化。
StreamBuilder 示例
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('StreamBuilder Example'),
),
body: StreamBuilderExample(),
),
);
}
}
class StreamBuilderExample extends StatelessWidget {
final StreamController<int> _controller = StreamController<int>();
StreamBuilderExample() {
// 模拟数据流
Timer.periodic(Duration(seconds: 1), (timer) {
_controller.add(timer.tick);
if (timer.tick >= 10) {
timer.cancel();
_controller.close();
}
});
}
Widget build(BuildContext context) {
return StreamBuilder<int>(
stream: _controller.stream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else if (!snapshot.hasData) {
return Center(child: Text('No Data'));
} else {
return Center(child: Text('Count: ${snapshot.data}'));
}
},
);
}
}
在这个示例中,StreamBuilder
监听 _controller
的数据流并根据数据更新 UI。这种方式非常适合处理异步数据流和实时更新的场景。