flutter中如何更好的使用stream
Flutter中的Stream
是用于处理异步事件流的一种重要工具。Stream
可以看作是一个异步数据序列,它能够按顺序提供多个异步事件。Flutter中的Stream
主要用于处理连续的数据更新,比如网络请求的结果、用户输入的事件、传感器数据等。以下是对Flutter中Stream
的详细说明,包括基础概念、常用方法、实际使用和高级用法。
基础概念
- Stream:表示一个可以接收异步事件的数据源。可以生成一个或多个值。
- StreamController:控制
Stream
,可以向其添加事件、错误以及关闭它。 - StreamSubscription:表示对
Stream
的监听,可以用来取消订阅。 - Sink:用来向
Stream
添加数据、错误、以及关闭。
常用方法
- Stream.fromIterable:创建一个从Iterable中获取数据的Stream。
- Stream.periodic:创建一个按周期生成数据的Stream。
- StreamController:用于创建自定义Stream,允许手动添加数据。
- StreamBuilder:Flutter提供的一个Widget,用于在构建Widget时监听Stream的数据变化。
示例代码
创建和监听Stream
-
使用
StreamController
创建和控制Stream:dart 复制代码 import 'dart:async'; void main() { // 创建StreamController final controller = StreamController<int>(); // 获取Stream final stream = controller.stream; // 监听Stream stream.listen((data) { print('Received data: $data'); }); // 添加数据到Stream controller.sink.add(1); controller.sink.add(2); controller.sink.add(3); // 关闭Stream controller.close(); }
-
使用
StreamBuilder
监听Stream并更新UI:dart 复制代码 import 'dart:async'; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('StreamBuilder Example')), body: Center( child: CounterWidget(), ), ), ); } } class CounterWidget extends StatefulWidget { @override _CounterWidgetState createState() => _CounterWidgetState(); } class _CounterWidgetState extends State<CounterWidget> { final StreamController<int> _controller = StreamController<int>(); int _counter = 0; void _incrementCounter() { _counter++; _controller.sink.add(_counter); } @override void dispose() { _controller.close(); super.dispose(); } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ StreamBuilder<int>( stream: _controller.stream, builder: (context, snapshot) { if (snapshot.hasData) { return Text('Counter: ${snapshot.data}'); } else { return Text('Counter: 0'); } }, ), ElevatedButton( onPressed: _incrementCounter, child: Text('Increment Counter'), ), ], ); } }
高级用法
-
Transforming Streams:使用
map
、where
等方法对Stream的数据进行转换和过滤。dart 复制代码 final stream = Stream.fromIterable([1, 2, 3, 4, 5]); final transformedStream = stream.where((data) => data % 2 == 0).map((data) => 'Number $data'); transformedStream.listen((data) { print(data); // 输出: Number 2, Number 4 });
-
Broadcast Streams:允许多个监听器同时监听一个Stream。
dart 复制代码 final controller = StreamController<int>.broadcast(); controller.stream.listen((data) => print('Listener 1: $data')); controller.stream.listen((data) => print('Listener 2: $data')); controller.sink.add(1); controller.sink.add(2); controller.sink.add(3); controller.close();
-
Combining Streams:使用
StreamZip
等方法组合多个Stream的数据。dart 复制代码 import 'package:async/async.dart'; final stream1 = Stream.fromIterable([1, 2, 3]); final stream2 = Stream.fromIterable(['A', 'B', 'C']); final combinedStream = StreamZip([stream1, stream2]); combinedStream.listen((data) { print('Combined data: $data'); // 输出: [1, A], [2, B], [3, C] });
使用场景
-
网络请求:在Flutter应用中,可以使用
Stream
处理网络请求的结果。例如,使用Stream
来监听网络数据流,并通过StreamBuilder
更新UI。dart 复制代码 import 'dart:async'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class DataFetcher { final StreamController<String> _controller = StreamController<String>(); Stream<String> get stream => _controller.stream; Future<void> fetchData() async { final response = await http.get(Uri.parse('https://api.example.com/data')); if (response.statusCode == 200) { _controller.sink.add(response.body); } else { _controller.sink.addError('Failed to fetch data'); } } void dispose() { _controller.close(); } } void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Stream Network Request Example')), body: Center( child: DataWidget(), ), ), ); } } class DataWidget extends StatefulWidget { @override _DataWidgetState createState() => _DataWidgetState(); } class _DataWidgetState extends State<DataWidget> { final DataFetcher _dataFetcher = DataFetcher(); @override void initState() { super.initState(); _dataFetcher.fetchData(); } @override void dispose() { _dataFetcher.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return StreamBuilder<String>( stream: _dataFetcher.stream, 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('Data: ${snapshot.data}'); } else { return Text('No data'); } }, ); } }
-
用户输入事件:可以使用
Stream
来处理用户输入事件,如文本框的输入变化。dart 复制代码 import 'dart:async'; import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Stream Input Example')), body: Center( child: InputWidget(), ), ), ); } } class InputWidget extends StatefulWidget { @override _InputWidgetState createState() => _InputWidgetState(); } class _InputWidgetState extends State<InputWidget> { final StreamController<String> _controller = StreamController<String>(); void _onTextChanged(String text) { _controller.sink.add(text); } @override void dispose() { _controller.close(); super.dispose(); } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextField( onChanged: _onTextChanged, decoration: InputDecoration( hintText: 'Type something...', ), ), StreamBuilder<String>( stream: _controller.stream, builder: (context, snapshot) { if (snapshot.hasData) { return Text('Input: ${snapshot.data}'); } else { return Text('Input:'); } }, ), ], ); } }
总结
Flutter中的Stream
提供了一种处理异步事件流的高效方式。通过Stream
和StreamBuilder
,可以在Flutter应用中处理和展示动态数据。无论是处理网络请求、用户输入还是传感器数据,Stream
都提供了灵活而强大的工具。掌握Stream
的使用,可以显著提升Flutter应用的响应速度和用户体验。
4o
请详细全面的讲解一下flutter中的stream
ChatGPT
Flutter中的Stream
是用于处理异步事件流的重要工具,类似于RxJava中的Observable。它们可以按时间顺序接收异步事件,可以是单个或多个值。Stream
特别适合用于处理网络请求、用户输入、传感器数据等连续的数据更新。以下是对Flutter中Stream
的详细全面讲解。
1. 基础概念
- Stream: 表示一个可以接收异步事件的数据源,能够生成一个或多个值。
- StreamController: 用于控制
Stream
,可以向其添加事件、错误以及关闭它。 - StreamSubscription: 表示对
Stream
的监听,可以用来取消订阅。 - Sink: 用于向
Stream
添加数据、错误以及关闭。
2. Stream类型
- 单订阅Stream (Single-subscription Stream) : 只能被一个监听器监听,例如
Stream.periodic
。 - 广播Stream (Broadcast Stream) : 可以被多个监听器同时监听,例如
StreamController.broadcast()
。
3. 创建Stream
使用StreamController
StreamController用于创建自定义的Stream,它可以添加事件、错误以及关闭流。
dart
复制代码
import 'dart:async';
void main() {
final controller = StreamController<int>();
// 获取Stream
final stream = controller.stream;
// 监听Stream
stream.listen((data) {
print('Received data: $data');
});
// 添加数据到Stream
controller.sink.add(1);
controller.sink.add(2);
controller.sink.add(3);
// 关闭Stream
controller.close();
}
使用Stream.fromIterable
从Iterable创建一个Stream。
dart
复制代码
void main() {
final stream = Stream.fromIterable([1, 2, 3, 4, 5]);
stream.listen((data) {
print('Received data: $data');
});
}
使用Stream.periodic
按周期生成数据的Stream。
dart
复制代码
void main() {
final stream = Stream.periodic(Duration(seconds: 1), (count) => count);
stream.listen((data) {
print('Received data: $data');
});
}
4. 监听Stream
使用listen
监听Stream中的数据、错误和完成事件。
dart
复制代码
void main() {
final stream = Stream.fromIterable([1, 2, 3]);
stream.listen(
(data) {
print('Data: $data');
},
onError: (error) {
print('Error: $error');
},
onDone: () {
print('Done');
},
);
}
5. 使用StreamBuilder
StreamBuilder
是Flutter中用于监听Stream
并根据数据变化更新UI的Widget。
dart
复制代码
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('StreamBuilder Example')),
body: Center(
child: CounterWidget(),
),
),
);
}
}
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
final StreamController<int> _controller = StreamController<int>();
int _counter = 0;
void _incrementCounter() {
_counter++;
_controller.sink.add(_counter);
}
@override
void dispose() {
_controller.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
StreamBuilder<int>(
stream: _controller.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Counter: ${snapshot.data}');
} else {
return Text('Counter: 0');
}
},
),
ElevatedButton(
onPressed: _incrementCounter,
child: Text('Increment Counter'),
),
],
);
}
}
6. 转换Stream
使用map, where等方法
对Stream的数据进行转换和过滤。
dart
复制代码
void main() {
final stream = Stream.fromIterable([1, 2, 3, 4, 5]);
final transformedStream = stream.where((data) => data % 2 == 0).map((data) => 'Number $data');
transformedStream.listen((data) {
print(data); // 输出: Number 2, Number 4
});
}
7. Broadcast Streams
允许多个监听器同时监听一个Stream。
dart
复制代码
void main() {
final controller = StreamController<int>.broadcast();
controller.stream.listen((data) => print('Listener 1: $data'));
controller.stream.listen((data) => print('Listener 2: $data'));
controller.sink.add(1);
controller.sink.add(2);
controller.sink.add(3);
controller.close();
}
8. Combining Streams
使用StreamZip等方法组合多个Stream的数据。
dart
复制代码
import 'package:async/async.dart';
void main() {
final stream1 = Stream.fromIterable([1, 2, 3]);
final stream2 = Stream.fromIterable(['A', 'B', 'C']);
final combinedStream = StreamZip([stream1, stream2]);
combinedStream.listen((data) {
print('Combined data: $data'); // 输出: [1, A], [2, B], [3, C]
});
}
9. 使用场景
网络请求
在Flutter应用中,可以使用Stream处理网络请求的结果。例如,使用Stream来监听网络数据流,并通过StreamBuilder更新UI。
dart
复制代码
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class DataFetcher {
final StreamController<String> _controller = StreamController<String>();
Stream<String> get stream => _controller.stream;
Future<void> fetchData() async {
final response = await http.get(Uri.parse('https://api.example.com/data'));
if (response.statusCode == 200) {
_controller.sink.add(response.body);
} else {
_controller.sink.addError('Failed to fetch data');
}
}
void dispose() {
_controller.close();
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Stream Network Request Example')),
body: Center(
child: DataWidget(),
),
),
);
}
}
class DataWidget extends StatefulWidget {
@override
_DataWidgetState createState() => _DataWidgetState();
}
class _DataWidgetState extends State<DataWidget> {
final DataFetcher _dataFetcher = DataFetcher();
@override
void initState() {
super.initState();
_dataFetcher.fetchData();
}
@override
void dispose() {
_dataFetcher.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return StreamBuilder<String>(
stream: _dataFetcher.stream,
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('Data: ${snapshot.data}');
} else {
return Text('No data');
}
},
);
}
}
用户输入事件
可以使用Stream来处理用户输入事件,如文本框的输入变化。
dart
复制代码
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Stream Input Example')),
body: Center(
child: InputWidget(),
),
),
);
}
}
class InputWidget extends StatefulWidget {
@override
_InputWidgetState createState() => _InputWidgetState();
}
class _InputWidgetState extends State<InputWidget> {
final StreamController<String> _controller = StreamController<String>();
void _onTextChanged(String text) {
_controller.sink.add(text);
}
@override
void dispose() {
_controller.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextField(
onChanged: _onTextChanged,
decoration: InputDecoration(
hintText: 'Type something...',
),
),
StreamBuilder<String>(
stream: _controller.stream,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Input: ${snapshot.data}');
} else {
return Text('Input:');
}
},
),
],
);
}
}
总结
Flutter中的Stream
提供了一种处理异步事件流的高效方式。通过Stream
和StreamBuilder
,可以在Flutter应用中处理和展示动态数据。无论是处理网络请求、用户输入还是传感器数据,Stream
都提供了灵活而强大的工具。掌握Stream
的使用,可以显著提升Flutter应用的响应速度和用户体验。
转载自:https://juejin.cn/post/7380730718295392266