
一、Stream概述
Stream是Dart中处理异步数据流的核心类型,可以产生多个异步事件。
#mermaid-svg-fwJcoHGJ6IFRcDre{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fwJcoHGJ6IFRcDre .error-icon{fill:#552222;}#mermaid-svg-fwJcoHGJ6IFRcDre .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fwJcoHGJ6IFRcDre .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fwJcoHGJ6IFRcDre .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fwJcoHGJ6IFRcDre .marker.cross{stroke:#333333;}#mermaid-svg-fwJcoHGJ6IFRcDre svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fwJcoHGJ6IFRcDre p{margin:0;}#mermaid-svg-fwJcoHGJ6IFRcDre .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-fwJcoHGJ6IFRcDre .cluster-label text{fill:#333;}#mermaid-svg-fwJcoHGJ6IFRcDre .cluster-label span{color:#333;}#mermaid-svg-fwJcoHGJ6IFRcDre .cluster-label span p{background-color:transparent;}#mermaid-svg-fwJcoHGJ6IFRcDre .label text,#mermaid-svg-fwJcoHGJ6IFRcDre span{fill:#333;color:#333;}#mermaid-svg-fwJcoHGJ6IFRcDre .node rect,#mermaid-svg-fwJcoHGJ6IFRcDre .node circle,#mermaid-svg-fwJcoHGJ6IFRcDre .node ellipse,#mermaid-svg-fwJcoHGJ6IFRcDre .node polygon,#mermaid-svg-fwJcoHGJ6IFRcDre .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-fwJcoHGJ6IFRcDre .rough-node .label text,#mermaid-svg-fwJcoHGJ6IFRcDre .node .label text,#mermaid-svg-fwJcoHGJ6IFRcDre .image-shape .label,#mermaid-svg-fwJcoHGJ6IFRcDre .icon-shape .label{text-anchor:middle;}#mermaid-svg-fwJcoHGJ6IFRcDre .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-fwJcoHGJ6IFRcDre .rough-node .label,#mermaid-svg-fwJcoHGJ6IFRcDre .node .label,#mermaid-svg-fwJcoHGJ6IFRcDre .image-shape .label,#mermaid-svg-fwJcoHGJ6IFRcDre .icon-shape .label{text-align:center;}#mermaid-svg-fwJcoHGJ6IFRcDre .node.clickable{cursor:pointer;}#mermaid-svg-fwJcoHGJ6IFRcDre .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-fwJcoHGJ6IFRcDre .arrowheadPath{fill:#333333;}#mermaid-svg-fwJcoHGJ6IFRcDre .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-fwJcoHGJ6IFRcDre .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-fwJcoHGJ6IFRcDre .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fwJcoHGJ6IFRcDre .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-fwJcoHGJ6IFRcDre .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fwJcoHGJ6IFRcDre .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-fwJcoHGJ6IFRcDre .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-fwJcoHGJ6IFRcDre .cluster text{fill:#333;}#mermaid-svg-fwJcoHGJ6IFRcDre .cluster span{color:#333;}#mermaid-svg-fwJcoHGJ6IFRcDre div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-fwJcoHGJ6IFRcDre .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-fwJcoHGJ6IFRcDre rect.text{fill:none;stroke-width:0;}#mermaid-svg-fwJcoHGJ6IFRcDre .icon-shape,#mermaid-svg-fwJcoHGJ6IFRcDre .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-fwJcoHGJ6IFRcDre .icon-shape p,#mermaid-svg-fwJcoHGJ6IFRcDre .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-fwJcoHGJ6IFRcDre .icon-shape rect,#mermaid-svg-fwJcoHGJ6IFRcDre .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-fwJcoHGJ6IFRcDre .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-fwJcoHGJ6IFRcDre .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-fwJcoHGJ6IFRcDre :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
数据源
Stream
事件1
事件2
事件N
完成/错误
二、创建Stream
void initState() {
super.initState();
_dataStream = Stream.periodic(
const Duration(seconds: 1),
(_) => (DateTime.now().millisecond % 100) / 10.0,
);
}
三、监听Stream
void _startListening() {
setState(() {
_isListening = true;
_data.clear();
});
_dataStream.listen(
(data) {
if (mounted) {
setState(() {
if (_data.length >= 20) _data.removeAt(0);
_data.add(data);
});
}
},
onError: (error) {
print('Stream error: $error');
},
onDone: () {
print('Stream done');
},
);
}
四、数据流图示
界面
监听器
Stream
数据源
界面
监听器
Stream
数据源
#mermaid-svg-GVOUqmNszpggSa7h{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-GVOUqmNszpggSa7h .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-GVOUqmNszpggSa7h .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-GVOUqmNszpggSa7h .error-icon{fill:#552222;}#mermaid-svg-GVOUqmNszpggSa7h .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-GVOUqmNszpggSa7h .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-GVOUqmNszpggSa7h .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-GVOUqmNszpggSa7h .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-GVOUqmNszpggSa7h .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-GVOUqmNszpggSa7h .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-GVOUqmNszpggSa7h .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-GVOUqmNszpggSa7h .marker{fill:#333333;stroke:#333333;}#mermaid-svg-GVOUqmNszpggSa7h .marker.cross{stroke:#333333;}#mermaid-svg-GVOUqmNszpggSa7h svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-GVOUqmNszpggSa7h p{margin:0;}#mermaid-svg-GVOUqmNszpggSa7h .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GVOUqmNszpggSa7h text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-GVOUqmNszpggSa7h .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GVOUqmNszpggSa7h .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-GVOUqmNszpggSa7h .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-GVOUqmNszpggSa7h .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-GVOUqmNszpggSa7h #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-GVOUqmNszpggSa7h .sequenceNumber{fill:white;}#mermaid-svg-GVOUqmNszpggSa7h #sequencenumber{fill:#333;}#mermaid-svg-GVOUqmNszpggSa7h #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-GVOUqmNszpggSa7h .messageText{fill:#333;stroke:none;}#mermaid-svg-GVOUqmNszpggSa7h .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GVOUqmNszpggSa7h .labelText,#mermaid-svg-GVOUqmNszpggSa7h .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-GVOUqmNszpggSa7h .loopText,#mermaid-svg-GVOUqmNszpggSa7h .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-GVOUqmNszpggSa7h .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-GVOUqmNszpggSa7h .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-GVOUqmNszpggSa7h .noteText,#mermaid-svg-GVOUqmNszpggSa7h .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-GVOUqmNszpggSa7h .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GVOUqmNszpggSa7h .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GVOUqmNszpggSa7h .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-GVOUqmNszpggSa7h .actorPopupMenu{position:absolute;}#mermaid-svg-GVOUqmNszpggSa7h .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-GVOUqmNszpggSa7h .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-GVOUqmNszpggSa7h .actor-man circle,#mermaid-svg-GVOUqmNszpggSa7h line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-GVOUqmNszpggSa7h :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
产生数据
事件1
更新数据
产生数据
事件2
更新数据
完成
onDone
五、Stream vs Future
| 返回值 | 单个值 | 多个值 |
| 完成时机 | 一次完成 | 持续产生 |
| 使用场景 | 单次操作 | 持续数据 |
| 监听 | await/catch | listen |
六、最佳实践
#mermaid-svg-ZVYAnTdp4uvNoq6t{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZVYAnTdp4uvNoq6t .error-icon{fill:#552222;}#mermaid-svg-ZVYAnTdp4uvNoq6t .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZVYAnTdp4uvNoq6t .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .marker.cross{stroke:#333333;}#mermaid-svg-ZVYAnTdp4uvNoq6t svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZVYAnTdp4uvNoq6t p{margin:0;}#mermaid-svg-ZVYAnTdp4uvNoq6t .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .cluster-label text{fill:#333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .cluster-label span{color:#333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .cluster-label span p{background-color:transparent;}#mermaid-svg-ZVYAnTdp4uvNoq6t .label text,#mermaid-svg-ZVYAnTdp4uvNoq6t span{fill:#333;color:#333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .node rect,#mermaid-svg-ZVYAnTdp4uvNoq6t .node circle,#mermaid-svg-ZVYAnTdp4uvNoq6t .node ellipse,#mermaid-svg-ZVYAnTdp4uvNoq6t .node polygon,#mermaid-svg-ZVYAnTdp4uvNoq6t .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZVYAnTdp4uvNoq6t .rough-node .label text,#mermaid-svg-ZVYAnTdp4uvNoq6t .node .label text,#mermaid-svg-ZVYAnTdp4uvNoq6t .image-shape .label,#mermaid-svg-ZVYAnTdp4uvNoq6t .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZVYAnTdp4uvNoq6t .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZVYAnTdp4uvNoq6t .rough-node .label,#mermaid-svg-ZVYAnTdp4uvNoq6t .node .label,#mermaid-svg-ZVYAnTdp4uvNoq6t .image-shape .label,#mermaid-svg-ZVYAnTdp4uvNoq6t .icon-shape .label{text-align:center;}#mermaid-svg-ZVYAnTdp4uvNoq6t .node.clickable{cursor:pointer;}#mermaid-svg-ZVYAnTdp4uvNoq6t .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .arrowheadPath{fill:#333333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZVYAnTdp4uvNoq6t .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZVYAnTdp4uvNoq6t .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZVYAnTdp4uvNoq6t .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZVYAnTdp4uvNoq6t .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZVYAnTdp4uvNoq6t .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZVYAnTdp4uvNoq6t .cluster text{fill:#333;}#mermaid-svg-ZVYAnTdp4uvNoq6t .cluster span{color:#333;}#mermaid-svg-ZVYAnTdp4uvNoq6t div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZVYAnTdp4uvNoq6t .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZVYAnTdp4uvNoq6t rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZVYAnTdp4uvNoq6t .icon-shape,#mermaid-svg-ZVYAnTdp4uvNoq6t .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZVYAnTdp4uvNoq6t .icon-shape p,#mermaid-svg-ZVYAnTdp4uvNoq6t .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZVYAnTdp4uvNoq6t .icon-shape rect,#mermaid-svg-ZVYAnTdp4uvNoq6t .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZVYAnTdp4uvNoq6t .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZVYAnTdp4uvNoq6t .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZVYAnTdp4uvNoq6t :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
是
否
是
否
创建Stream
开始监听
更新UI
有新数据?
处理数据
已满20条?
移除旧数据
添加新数据
重新渲染
要点:
- 及时取消监听避免内存泄漏
- 限制数据量防止内存溢出
- 检查mounted状态
- 处理错误和完成事件
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

