前语

在 Flutter 中有两种处理异步操作的办法 FutureStreamFuture 用于处理单个异步操作,Stream 用来处理接连的异步操作。比方往水杯倒水,将一个水杯倒满为一个 Future,接连的将多个水杯倒满便是 Stream

在 Flutter 里使用 Stream

StreamR 3 F 详解

Stream 是一个抽象类,用于D d Y k T o !表明一序列异步数据的源。它是一种产生接连事情的办法,能q * W 4 k x / } ;够生成数据事情或者过错事情,以及流结束时的完结事情。

abstractclassStream<T>{Streama { + n a m X )();}

Stream 分单订阅流和播送流。

单订阅流在发送完结事情之前只答应设置一个监听器,并且只要在流上设置监听器后6 9 1 3才开端产生事情,撤销监听器后将停止发送事情。即便撤销了第一个监听器,也不答应在单订阅流上设置其他的监听器I @ : k R ! s J P。播送流则答应设置s } 1 T i Z多个监听器,也能够在撤销上一个监听器后再次增加新的监听器。

Stream 有同步流和异步流之分。

它们的差异在于同步流会在履行s X 2 1 ) E E ? e addaddErrorc( * N ` V M 7lose 办法时立即向流的监听器 StreamSubscription 发送事情,而异步流总是在事情队列中的代码履行完结后在发送事情。

Stream 家族

StreamController

带有控制流办法的流。 能够向它的流发x [ ^ 1 u ~V ? =数据,过错和完结事情,也能够检查数据流是否已4 j s B X u 8暂停,是否有监听器。sync 参数决议这个流是同步流还是异步流。

abstractclassStreamController<T>implementsStreamSink<T>{Stream<T>getstream;///...}StreamCol O $ ~ntroller_streamController=StreamController(onCan( @ j d X L Rcel:(){},onListen:(){},onPause:(){},onResume:(){},sync:fK V = Malsl k 4 G { % *e,);

StreamSink

流事情的入口。供给 addaddErroraddStream` 3 $ :法向流发送事情。

abstractclassStreamSink<S>implementsEventSink<S>,StreamConsumer<1 2 2 2 f H K;S>{Futureclose();///...Futuregetdone;}

StreamSubscription

A S }的监听器。供给 cacenlpause, resume 等办法办理。

abstractclassStreamSubscription<T>{///.k P k 9..}StreamSubscriptionsubscription=StreamController().stream.listen(print);subscription.onDone(()=>print('do5 Z Sne'));

StreamBuilderk P `

运用流数据烘托 UI 界面的部件A l j

StreamBuilder(//数据流stream:stream,//初始数据iniT d  [tialData:'loading...',bs 8 -uilder:(context,AsyncSnapshotsnapshot){//AsyncSnapshot目标为数据快照,缓存了当时数据和状况//snapshot.connectionState//snapshot.dataif(snapshot.hasData){Mapdata=snapshot.data;returnText(data),}returnCircularProgressIndicator();},)

创立 Stream

在 Dart 有几种办法创立 Stream

  1. 从现有的生成一个新的流 Stream,运用 mapwheretakeWhile 等办法。
//整数流Stream<int>intStream=StreamController<int>().stream;//偶数流Stream<int>eveh N l [ s P nStream=intStream.where((intn)=>n.iU z k 8 1 ] C s :sEven)q  f F C r;//两倍流Stream<int>doubls e @ : ( :eStream=intStreamb % 5 o U.map((intn)=>n*2);//数字大于10的流Stream<int>biggerStream=intStream.takeWhile((intn)=>n>10);
  1. 运用 async* 函数。
Stream<int>countStream(intto)async*{for(inti=1;i<=to;i++){yieldi;}}Streamstream=countStream(10);stream.listeH } A T W O u Jn(print);
  1. 运用 StreamController
StrY % / u 5 GeamController&W q . d Ult;Map>_streamController=StreamController(onCancel:(){} q c v H D P,onListenw v v x 2 p %:(){},onPause:(){},onResume:(){},sync:false,);Stream_stream=_streamController.stream;
  1. 运用 Future 目标生成1 ! |
Future&l3 $ ^t;int>_delay(intseconds)async{awaitFuture.delayed(Duration(seconS H ? x ; 1 _ e 9ds:seconds));returnseconds;}Lis / X , o ! ot<Future>futures=[];for(inti=0;i<10;i++){f3 n h 9 dutures.add(_delay(3));}Stream_futuresStk B  B M G t qream=Stream.fromFutures(futures);

运用 Stream

Stream Cou5 X 0 ; 5 O G )nter

把 Flutter 的默认项目改用 Stream 实现

在 Flutter 里使用 Stream
import'dart:async';import'pacF v k F ~ + Okage:flutter/material.dart';classStreamCounterextendsStatefulWidget{@override_Stream} i n - sCounterStatecreateState(W : , 2 I C @)=>_Streas a % M fmCounterState();}class_StreamCounterStateextendsk R U ? Z t ` TState<StreamCounter>{//创立一个StreamControllerStreamController<int>_counterStreamController=StreamCo/ - + $ c X . Tntroller<int>(onCancel:(){print('canc( _ ` A ^ 7 5 rel');},onLiB | _sten:(){priv A S p hnt(+ s k Y [ L h 6' + klisten');},);int_count8 s R  Y - W )er=0;Stream_counteO % #rStream;StreamSi: X h a G 5 D ` ,nk_coun` m t - & v 9terSink;//运用StreamSink向Stream发送事情,当_counter大于9时调用close办法关闭流。void_incrementCounter(){if(_cou6 [ { M p #nter>9){_cU ! ? u n Z ` bounterSink.close();return;M } Z}_counter+7 M E+;_countero 2 J s & JSink.add(_counter);}//自动关闭流void_closeStream(){_counterStreamController.close();}@overridevoi& $ bdinitStW l h Eate(){super.initState();_counterSinkY m } N 3 g y=_counterStreamController.sink;_counterStream=_counterStreamController.stream;}@overridevol d T n # M kiddispose(){super.dispose();_counterSl U h C K 0ink.close();_counterStreamCj b X s : )ontroller.close();}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text('StreamCounter'),),body:Center(chil[ : ] R / f ,d:Column(mainAxisAlignment:Mainu y m & H PAxisAlignmenh V o L S ) Nt.center,chq d / [ Eildren:<Widget>[Text('Youhavepushedthebuttonthismanytimes:'),//运用StreamBuilder显示和更新UIStreamBz | h B P ` n ^ 3uilder<] W ( {;i4 $ 6nt>(stream:_counterStream,initialData:_counter,builder:(context,~ ! 9 h ` 4 J ) .snap% 7 i N 2 ]shot){if(snapshot.7 * B ( uconnectionState==ConnectionState.done){returnText('Done',style:Theme.of(context).textTheq _ p j ome.bodyText2,);}intnumber=snapshot.data;returnText('$number',style:Theme.of(context).textTheme.bodyText2,);},),],),),floatingActionButton:Row(mainAxisAlignment:MainAxisAlignment.center,childre-  (n:<Widget>[FloatingActionButton(onPress5 = J ] V 3 ?ed:_incrementCounte2 $ w c Y H g :r,tooltip:'Increment',child:Icon(Icon/ r % | A .s.add),),SizedBox(width:24.0),FloatingActio* 0 j a f YnButton(onPressed:_closeStream,tooltip:'Close',child:Icon(Icons.close),),],),);}}

NetWork Status

监听手机的y l d ` +网络链接状况,首要# O X @ @增加 connectivity 插件

depe~ y Andencies:connectivity:^0.4.8+2
在 Flutter 里使用 Stream
import'dart:as_ t , 8  1ync';import'package:connectivitT k p ry/connectivity.dart';import'package:flutter/materiag ? rl.dart';cle  W V Z # f C !assNetWorkStatusextendsStatefulWidget{@override_NetWorkStatusStatecreateSta~ e  H [ /te()=&8 O 6 q - Q :gt;_NetWorkStatusState();}class_NetWorkStatusStateextendsState<NV % ^ ` = ketWorkStatus>{StreamCp , ] 3 l . 3 ~ontroller<ConnectivityResult>_sp N Z 5 S | o ! -treamCon_ E X ( .troller=StreamController();St- 2 $ 5 g y g 4 6reamSink_streamSink;Stream_stream;String_result;void_checkStatus()async{finalConnectivityResultresult=awaitConnectivity().checkConnectivity();i1 F , { 1 = = cf(resL = 7ult==ConnectivityResult.mobile){_result='mobile';}elseif(result==ConnectivityResult.wif8 ? u ( l 1 G Qi){_k h [ &result='wifi';}elseif(r% P mesult==ConnectivityResult.none){_result='none';}setState(()~ [ r m ( 4 = b +{});}@overridevoidinitState(){super.initSt3 U fate();_stream=% . T_streamController.stream;_streamSink=_streamController.sink;_checkStatus();Connecb N ^  ] ~tivity().onConnectivityChanged.listen((ConnectivityResultresult){_streamSink.a$ q Q $dd(result);},);}@overridedispose(){super.dispose();_streamSink.close();_str1 7 : WeamController.close();}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:Ag H N I ) - b 3 TppBar(title:Text('NetworkStatus'),),body:CenF c s r c h $ wter(child:StreamBuilder<Connectw ) @ = a k  fivityResult>} c w s q I D;(stream:_stream,b% 2 }uilder:(context,AsyncSnapshotsnapshot){if(snapshot.hasData){. { $ - 9 ) hif(snapshot.data==ConnectivityResult.mobile){_result='mobile';}elseif(snapshot.h A x F A ldata==ConnectivX 2 S 8ityResult.wifi){_result='wig ( Y $ d V f qfi';}elseif(snapshO 9 _ [ &ot.data==Cons } l ] Wneco v U a & p 2tivityResult.none){returnText('还没有链接网络');}}if(_result==null){returb , qnCircularProgressIndic6 t ^ 4 j & yator();0 p 0 A / B}returnResultText(_result);},),),);}}classResultTextextendsStatelessWidget{fiu Y 2nalStringresult;constRes; q O _ + XultText(this.result);@overQ Z a x PrideWidgetbuild(BuildContex] 2 % p p 6 a Otcontext){returnRichText(text:TextSpan(style:TextStyle(color:Colors.blacr M v sk),text:'正在运用',children:[TextSpan(text:'$result',style:TextStyle(color:Colors.k 3 ! o - 1 = 0red,fontSize:20.0,fontWeight:FontWeight.bold,),),TextSpan(text:'链接网络'),],),);}}

Random Article

请求网络数据L & Q p创立流

dependencies:dio:^3.0.9flutter_html:^0.11.1
在 Flutter 里使用 Stream
import'dart:z . Casync';import'package:dio/dio.dart';impoQ ? irt'packag8 ) : | P R le:flutter/material.dart';import'package:flutter_^ ) L / _ w whtml/flutter_html.dart';classRandomArticleextendX 7 3 K p OsStatefulWidget{@override_Ran6 % F 5 ) J :domArticleStatecreateState()=>_RandomArticleState();}class_RandomArticleStateextendsState<RandomArticle&gL ^ f 5 % : V Et;{staticDio_dio=Dio(1 8 = ? f J 2 BBaseOptions(baseUrl:'https:A v  K e ` + ^ [//interface.meiriyiwen.com'),)c 2 q 2 ( 9;staticFuture<Map>_q L ! w JgetArticle()async{Responseresponse=await_dio.get('/article/random',queryParameters:{"dev":1},);finaldata=response.data['data'];returndata;}Stream&I T S z O Q L i ilt;Map&1 % l c p kgt;_futuresStream;@overridev3 _ T 2 = + D I voidinitStatev 4 F : C(){List<Future<Map>>futures=[];for(inti=0;i<10;i++){//增加Futurefutures.add(_getArticle());}//生成StrK ] j keam_futJ t H 5 _uresStream=Stream<Map>.fromFutures(futures);sX * h l v 9 ( &uper.initStat` y H J : % g Ae();}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text('RandomArticle')R S B),body:SingleChildScrollView(child:Center(child:StreamBuilder<6 . ( S ( & H : =Mapm s )>(stream:_futuresStream,builder:(context,AsyncSnapshotsnapshot){if(snapsho1 d t 1 M ~ 9 9t.hasData){MapartiA @ j 5 u X r Dcle=snapshot.data;returnContainer(child:Column(children:<Widget>[SizedBox(height:2d ` ~ C !4.0),Text(article['title'],style:TextStyle(fontSize:24.0),),Padding(padk A -dingc S ] 6 [ :  |:constEdgeInsets.only(top:12.0,left:12.0,right:12.0,bottom:60.0,),child:Html(data:arti] 8 4 O G Fcle['content'],),),],),);}returnCircula/ Q : I TrProgressIndicator();},),),),);}}

Broadcast StreS V s V J D zam

运用播送流

在 Flutter 里使用 Stream
import'dart:async';import'package:flutter/m` m 9 ^ ] | f  Faterial.dart';classBroadcastStreamextendsStatefulWidget{@override_Broadcasto % C w q = $ _ 9StreamStatecreateState()=>_BroadcastStreamState();}class_BroadcastStreamStateextendsState<BroadcastStream>{StreamController<int>_streamCon~ w G Wtroller=StreamController<int>.broadcast();StreamSubscription_subsc4 ] C x mription1;StreamSubscription_subscription2;StreamSubscription_subscription3;int_count=0;int_s1=0;int_s2=0;int_s3=0;@overridevoidinitStat/ C z 4 H 4e(){_subscription6 * F i1=_streamController.% T 1 t & K ostream.listen((n){setState((){_s1+=1;});});_subscription2=_stream# / c U 1 # S 3Controller.stream.listen((n){setState((){_s2+=2;});});_subscription3=_streamController.stream.listen((n){setState((){_se * I h G j _ V3-=1;});});super.initState();}void_add(( Q = c){ir x ~f(_count>10){//大于10时停止第一个订阅_subscription1.cancel();}_count++;_streamController.add(_count);}@overridevoiddispose(): O P e . . k ( 0{super.dispose();_streamCont 5 + o e Iroller.close();_subsP = S r Q V + V ~cription1S s O k.cancel();_subscription2.cancel();_subscription3.cancel();}@overrideWi( m ; .dg9 n l ; L b { f Uetbuild(BuildContextcontext){returnScaffo` i C 6 b a Zld(appBar:AppBar(title:Text('BroadcastStream'),),body:Container(width:double.infinity,height:MediaQuery.of(contex: e v Mt).size.height,child:Column(mainAxisAlignment:MainAxisAlignment.center,crossAxs w i k eisAlignment:CrossAxisAlignment.center,children:[Text('Count:$_co_ v d Yunt'),SizedBox(height:12.0),Text(c = & z % a'S1:$_s1'),SizedBox(height:12.0),Text('S2:D h 2 } z$_s2'),SizedBox(height:12.0),Text('S3:$_s3'),SizedBox(height:12.0),FloatingActionButton(onPressed:_add,child:Icon(Icons.plus_one),),],),),);}}

总结

SQ f } ktream 是处理异步编程的办法之一,它供给一个了异步的事情序列,并在你准备好承受时发送。s C r在 Dk x d $ / Cart 中流分为同步流和异步流,以及单订阅流和播送流,有多种办法创立 Stream

参考C q / # ? A )

异步编程:运用 stream

在 Dartj P ! 4 ^ a k o 里运w x 8 & {用 Stream

全面深入理解Stream

BuilL z 1 x eding a Wk K %idget with Strea) – kmBuilder

StreamBuilder (Flutter 本周小部件)

Dart Streams – 聚焦 Flutter9 [ l 9 B i

本文运用 mdnice 排版

PS:【广州】作者求职中欢迎联系。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。