本文基於以下文章翻譯整合:
https://medium.com/@ayushpguptaapg/using-streams-in-flutter-62fed41662e4
https://www.woolha.com/tutorials/flutter-using-streamcontroller-and-streamsubscription
Stream與RxJava的Observable類似,就像它的名字,它是一系列的異步事件。你可以在一個地方定義一個Stream,在其他地方向這個Stream添加數據或者監聽它數據的變化,以此來更新你的Widget。
首先,開始之前,別忘記導包:
import 'dart:async';
1、創建一個簡單的Stream
使用Stream.fromFuture來創建一個Stream:
@override
void initState() {
super.initState();
print("Creating a sample stream...");
Stream<String> stream = new Stream.fromFuture(getData());
print("Created the stream");
stream.listen((data) {
print("DataReceived: "+data);
}, onDone: () {
print("Task Done");
}, onError: (error) {
print("Some Error");
});
print("code controller is here");
}
Future<String> getData() async {
await Future.delayed(Duration(seconds: 5)); //Mock delay
print("Fetched Data");
return "This a test data";
}
注意:‘code controller is here’在Stream發射數據之前就已打印,說明操作是異步的。
代碼分解:首先我們創建了一個Stream,它從getData()函數中獲取數據,getData()這個函數在5秒延遲之後返回一個字符串。然後,我們通過.listen()方法監聽Stream的數據,listen方法包含接收數據處理,和兩個onDone onError 可選參數,onDone意味着流已經完成,一旦進入到這個回調,流會自動關閉。
當任務完成後,應該關閉Stream(流),否則當你的App很複雜或者你有很多Stream時,性能會有損失。
2、使用SteamController創建一個Stream
SteamController構造函數有以下幾個參數:
參數 | 類型 |
---|---|
onListen | Function |
onPause | Function |
onResume | Function |
onCancel | Function |
sync | boolean (default: false) |
listen方法有以下幾個參數:
參數 | 類型 |
---|---|
onListen (必須提供 ) | Function |
onDone | Function |
onError | Function |
cancelOnError | bool |
StreamController<String> streamController = new StreamController();
@override
void initState() {
super.initState();
print("Creating a StreamController...");
streamController.stream.listen((data) {
print("DataReceived: " + data);
}, onDone: () {
print("Task Done");
}, onError: (error) {
print("Some Error");
});
streamController.add("This a test data");//通過add發送數據
streamController.addError(new Exception('An exception'));//可以通過addError發出異常
print("code controller is here");
}
@override
void dispose() {
streamController.close(); //不再需要時,Streams必須關閉
super.dispose();
}
注意這裏onDone()方法未被調用,因爲Stream還活着,它沒有被關閉。這就是爲什麼要關閉Stream(本例在dispose()方法中關閉)避免內存泄漏問題。
3、StreamSubscription
listen() 方法返回StreamSubscription:
subscription向listener提供事件,並持有用於處理這些事件的回調。subscription也可用於取消訂閱事件,或暫時暫停流中的事件。
subscription.pause(Future.delayed(const Duration(seconds: 5)));
需要牢記的是:當訂閱不需要時別忘記取消訂閱。
4、Broadcast Streams
Dart中有兩種類型的流:單訂閱關係的流( single-subscription streams )和廣播流(broadcast streams)。他們的主要區別是廣播流可以有多個訂閱者。
StreamController<String> streamController =
new StreamController.broadcast(); //Add .broadcast here
@override
void initState() {
super.initState();
print("Creating a StreamController...");
//First subscription
streamController.stream.listen((data) {
print("DataReceived1: " + data);
}, onDone: () {
print("Task Done1");
}, onError: (error) {
print("Some Error1");
});
//Second subscription
streamController.stream.listen((data) {
print("DataReceived2: " + data);
}, onDone: () {
print("Task Done2");
}, onError: (error) {
print("Some Error2");
});
streamController.add("This a test data");
print("code controller is here");
}