# Flutter - Stream ## 基礎概念 Stream和Future都是Dart:async庫的核心API,我們常用於異步的操作。 若把它想成機器以下是他的特點: 1. 一個隨時可以接收東西的入口 2. 這個機器執行的過程可以進行加工 3. 機器做完後產品隨時都有可能出來 4. 先進先出 > 機器 - StreamController 機器入口 - sink,可以使用`add`的方式放入產品 機器出口 - stream,但由於不知道何時會出來所以需要透過`listen`的方式進行監聽 ### Stream的種類  #### 單訂閱流Stream * 只允許有一個listener * 沒有listener就不會生成事件,即使你仍然在sink.add更多事件。 * listener取消後也不允許再被監聽 * 常用於: 下載,訂閱流來知道下載進度 ```dart StreamController controller = StreamController(); controller.stream.listen((data)=> print(data)); controller.stream.listen((data)=> print(data)); //噴錯: Bad state: Stream has already been listened to. 單訂閱流不能有多個收聽者。 controller.sink.add(123); ``` #### 多訂閱流BroadcastStream * 允許任意數量的listener * 無論是否有收聽者,他都能產生事件。所以**中途進來的收聽者將不會收到之前的消息**。 * asBroadcastStream ```dart StreamController controller = StreamController(); //轉化為廣播流 Stream stream = controller.stream.asBroadcastStream(); stream.listen((data)=> print(data)); stream.listen((data)=> print(data)); controller.sink.add(123); ``` ### 如何使用Stream #### 宣告 ```dart //任一類型 StreamController controller = StreamController(); controller.sink.add(123); controller.sink.add("xyz"); controller.sink.add(Anything); //處理int類型 StreamController<int> numController = StreamController(); numController.sink.add(123); //處理完流記得進行關閉 controller.close(); numController.close(); ``` #### 完整流程 ```dart StreamController controller = StreamController(); //監聽出口當有data產生時印出資料 StreamSubscription subscription = controller.stream.listen((data)=>print("$data")); controller.sink.add(123); //處理完記得進行關閉 subscription.cancel(); ``` 輸出 ``` 123 ``` ### 篩選Stream #### where ```dart stream.where((event){}) ``` #### take 當傳輸次數超過這一個述自將自動關閉 ```dart stream.take(2) ``` ### transform 要配合StreamTransformer進行使用,以下範例為輸入**數字**回應**字串** ```dart StreamController<int> controller = StreamController<int>(); //這邊進行轉換 final transformer = StreamTransformer<int,String>.fromHandlers( handleData:(value, sink){ if(value==100){ sink.add("bingo"); } else{ sink.addError('nono try again'); } }); controller.stream .transform(transformer) .listen( (data) => print(data), onError:(err) => print(err)); controller.sink.add(23); //controller.sink.add(100); ``` ### StreamBuilder 以下使用計時器當作範例: ```dart //每隔一秒生成一個數字 Stream<int> counter() { return Stream.periodic(Duration(seconds: 1), (i) { return i; }); } ``` ```dart Widget build(BuildContext context) { return StreamBuilder<int>( stream: counter(), // builder: (BuildContext context, AsyncSnapshot<int> snapshot) { if (snapshot.hasError) return Text('Error: ${snapshot.error}'); switch (snapshot.connectionState) { case ConnectionState.none: return Text('沒有Stream'); case ConnectionState.waiting: return Text('等待資料...'); case ConnectionState.active: return Text('active: ${snapshot.data}'); case ConnectionState.done: return Text('Stream 已關閉'); } return null; // unreachable }, ); } ``` ## 實作 ## 參考資料 https://book.flutterchina.club/chapter7/futurebuilder_and_streambuilder.html#_7-6-1-futurebuilder https://juejin.cn/post/6844903686737494023 https://juejin.cn/post/6844903689082109960 ###### tags: `flutter`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up