flutter Stream流的理解和运用
2021-09-03 本文已影响0人
三也视界
1.Stream和Future区别
Future 表示一个不会立即完成的计算过程。与普通函数直接返回结果不同的是异步函数返回一个将会包含结果的 Future。该 Future 会在结果准备好时通知调用者。
Stream 是一系列异步事件的序列。其类似于一个异步的 Iterable,不同的是当你向 Iterable 获取下一个事件时它会立即给你,但是 Stream 则不会立即给你而是在它准备好时告诉你。
2.Stream分类
流可以分为两类:
-
单订阅流(Single Subscription),这种流最多只能有一个监听器(listener)
-
多订阅流(Broadcast),这种流可以有多个监听器监听(listener)
3.Stream四个核心对象
- Stream 事件源
- StreamController 为了方便控制Stream的流控制器
- StreamSink 事件输入口
- StreamSubscription 管理事件订阅
4.一个简单的实例,来理解这几个对象
- 创建对象(先创建StreamController控制,再由控制器创造StreamSink,Stream对象)
///流事件控制器
// ignore: close_sinks
StreamController<int> _streamController = StreamController(
onListen: (){
print("onListen");
},
onCancel: (){
print("onCancel");
}
);
Stream _stream;
Stream _eventStream;
StreamSink _sink;
int _count = 0;
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_streamController.close();
_sink.close();
}
///初始化操作
@override
void initState() {
// TODO: implement initState
super.initState();
///流事件
_stream = _streamController.stream;
///事件入口
_sink = _streamController.sink;
}
- 在需要订阅的组件外层包裹StreamBuild进行事件订阅(builder是将获取的数据进行操作,再展示到组件上的目的)
StreamBuilder(
stream: _stream,
initialData: _count,
builder: (context , AsyncSnapshot snapshot){
///snapshot携带事件入口处闯进来的数据,用snapshot.data获取数据进行处理
if(snapshot.connectionState == ConnectionState.done){
return Text('Done',style: TextStyle(fontSize: 14 , color: Colors.blue),);
}
int number = snapshot.data;
return Text(
"$number",
style: TextStyle(fontSize: 14 , color: Colors.blue),
);
},
)
- 事件传入
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
child: Icon(Icons.add),
tooltip: "Increment",
onPressed: ()=>_incrementCounter(),
),
SizedBox(width: 20,),
// FloatingActionButton(
// child: Icon(Icons.close),
// tooltip: "Close",
// onPressed: ()=>_closeStream,
// ),
],
),
void _incrementCounter(){
if(_count > 9){
_sink.close();
return;
}
_count++;
///事件入口对象传入数据
_sink.add(_count);
}
以上就是Stream的基本使用了
完整代码
import 'dart:async';
import 'package:flutter/material.dart';
class StreamOnePage extends StatefulWidget {
@override
_StreamOnePageState createState() => _StreamOnePageState();
}
class _StreamOnePageState extends State<StreamOnePage> {
///流事件控制器
// ignore: close_sinks
StreamController<int> _streamController = StreamController(
onListen: (){
print("onListen");
},
onCancel: (){
print("onCancel");
}
);
Stream _stream;
Stream _eventStream;
StreamSink _sink;
int _count = 0;
void _incrementCounter(){
if(_count > 9){
_sink.close();
return;
}
_count++;
_sink.add(_count);
}
void _closeStream(){
_streamController.close();
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_streamController.close();
_sink.close();
}
@override
void initState() {
// TODO: implement initState
super.initState();
///流事件
_stream = _streamController.stream;
///事件入口
_sink = _streamController.sink;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Stream"),),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('You have pushed the button this many times:'),
StreamBuilder(
stream: _stream,
initialData: _count,
builder: (context , AsyncSnapshot snapshot){
///snapshot携带事件入口处闯进来的数据,用snapshot.data获取数据进行处理
if(snapshot.connectionState == ConnectionState.done){
return Text('Done',style: TextStyle(fontSize: 14 , color: Colors.blue),);
}
int number = snapshot.data;
return Text(
"$number",
style: TextStyle(fontSize: 14 , color: Colors.blue),
);
},
)
],
),
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FloatingActionButton(
child: Icon(Icons.add),
tooltip: "Increment",
onPressed: ()=>_incrementCounter(),
),
SizedBox(width: 20,),
// FloatingActionButton(
// child: Icon(Icons.close),
// tooltip: "Close",
// onPressed: ()=>_closeStream,
// ),
],
),
);
}
}
Stream操作符:
_streamDuration() async {
Duration duration = Duration(seconds: 1);
Stream<int> stream3 = Stream.periodic(duration, (data) => data);
//stream3 = stream3.take(10);//限制发送次数
stream3 = stream3.takeWhile((element) => element < 10);
stream3 = stream3.skip(2);
// List<int> listData = await stream3.toList();//一次性返回
// var length = await stream3.length;//数据长度
// stream3 = stream3.map((data) => data + 1);//数据变化
// stream3 = stream3.where((data) => data>3);//数据筛选
// stream3 = stream3.where((data) => data<6);
stream3 = stream3.expand((data) => [data, data]);
stream3.listen((data) {
print("expand==>$data");
}, onError: (error) {
print("$error");
});
// print("length==>$length");
// for (int i in listData) {
// print("stream3==>$i");
// }
// await for(int i in stream3){
// print("stream3==>$i");
// }
}
Stream多订阅流
import 'dart:async';
import 'package:flutter/material.dart';
class BroadcastStreamPage extends StatefulWidget {
@override
_BroadcastStreamPageState createState() => _BroadcastStreamPageState();
}
class _BroadcastStreamPageState extends State<BroadcastStreamPage> {
// ignore: close_sinks
StreamController _streamController = StreamController.broadcast();
StreamSubscription _subscription1;
StreamSubscription _subscription2;
StreamSubscription _subscription3;
int _count = 0;
int _s1 = 0;
int _s2 = 0;
int _s3 = 0;
_add(){
if(_count > 9){
_subscription1.cancel();
}
_count++;
_streamController.add(_count);
}
@override
void initState() {
// TODO: implement initState
super.initState();
_subscription1 = _streamController.stream.listen((event) {
setState(() {
_s1 +=1;
});
});
_subscription2 = _streamController.stream.listen((event) {
setState(() {
_s2 +=2;
});
});
_subscription3 = _streamController.stream.listen((event) {
setState(() {
_s3 -=1;
});
});
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
_streamController.close();
_subscription1.cancel();
_subscription2.cancel();
_subscription3.cancel();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("BroadcastStream"),
),
body: Column(
children: [
Text('Count: $_count'),
SizedBox(height: 12.0),
Text('S1: $_s1'),
SizedBox(height: 12.0),
Text('S2: $_s2'),
SizedBox(height: 12.0),
Text('S3: $_s3'),
SizedBox(height: 12.0),
FloatingActionButton(
onPressed: _add,
child: Icon(Icons.plus_one),
),
],
),
);
}
}