# 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
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.