Stream4
Subscribing to stream events¶
我們將使用 Subscription 來正常處理事件、錯誤並關閉訂閱。¶
Code¶
import 'package:flutter/material.dart';
import 'stream.dart';
import 'number.dart';
import 'dart:async';
import 'dart:math';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Stream',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
// home: StreamHomePage(),
home: StreamNumber());
}
}
class StreamHomePage extends StatefulWidget {
@override
_StreamHomePageState createState() => _StreamHomePageState();
}
class _StreamHomePageState extends State<StreamHomePage> {
Color? bgColor;
ColorStream? colorStream;
@override
void initState() {
colorStream = ColorStream();
changeColor();
super.initState();
}
changeColor() async {
// await for (var eventColor in colorStream!.getColors()) {
// setState(() {
// bgColor = eventColor;
// });
// }
colorStream?.getColors().listen((eventColor) {
setState(() {
bgColor = eventColor;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stream'),
),
body: Container(
decoration: BoxDecoration(color: bgColor),
));
}
}
class StreamNumber extends StatefulWidget {
const StreamNumber({super.key});
@override
State<StreamNumber> createState() => _StreamNumberState();
}
class _StreamNumberState extends State<StreamNumber> {
int lastNumber = 0;
StreamTransformer? transformer;
NumberStream? numberStream;
StreamController? numberStreamController;
StreamSubscription? subscription;
@override
void initState() {
numberStream = NumberStream();
numberStreamController = numberStream?.controller;
Stream? stream = numberStreamController?.stream;
// stream?.listen((event) {
// setState(() {
// lastNumber = event;
// });
// });
// transformer = StreamTransformer<dynamic, dynamic>.fromHandlers(
// handleData: (value, sink) {
// sink.add(value * 10);
// },
// handleError: (error, trace, sink) {
// sink.add(-1);
// },
// handleDone: (sink) => sink.close());
// stream?.transform(transformer!).listen((event) {
// setState(() {
// lastNumber = event;
// });
// }).onError((error) {
// setState(() {
// lastNumber = -1;
// });
// });
subscription = stream?.listen((event) {
setState(() {
lastNumber = event;
});
subscription?.onDone(() {
print('OnDone was called');
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(lastNumber.toString()),
ElevatedButton(
onPressed: () => addRandomNumber(),
child: Text('New Random Number'),
),
ElevatedButton(
onPressed: () => stopStream(),
child: Text('Stop Stream'),
)
],
),
),
);
}
void addRandomNumber() {
Random random = Random();
int myNum = random.nextInt(10);
if (!numberStreamController!.isClosed) {
numberStream?.addNumberToSink(myNum);
} else {
setState(() {
lastNumber = -1;
});
}
}
void stopStream() {
numberStreamController?.close();
}
}
程式碼解釋¶
這段程式碼是一個 Flutter 應用程式,主要包含兩個部分:StreamHomePage 和 StreamNumber。
StreamHomePage 是一個 StatefulWidget,它使用一個 ColorStream 來改變背景顏色。在 initState 方法中,它創建一個 ColorStream 對象並調用 changeColor 方法來監聽 Stream 的事件。當 Stream 中有新的顏色時,它會更新 bgColor 的值並觸發界面的重新渲染。
StreamNumber 也是一個 StatefulWidget,它使用一個 NumberStream 來生成隨機數字。在 initState 方法中,它創建一個 NumberStream 對象並設定一個監聽器來監聽 Stream 的事件。當 Stream 中有新的數字時,它會更新 lastNumber 的值並觸發界面的重新渲染。
此外,StreamNumber 還提供了兩個按鈕:一個用於生成新的隨機數字並將其添加到 Stream 中,另一個用於停止 Stream。當用戶點擊 "New Random Number" 按鈕時,addRandomNumber 方法會被調用,生成一個新的隨機數字並將其添加到 Stream 中。當用戶點擊 "Stop Stream" 按鈕時,stopStream 方法會被調用,關閉 Stream。
這個應用程式展示了如何在 Flutter 中使用 Stream 來處理異步數據。透過 Stream,你可以在數據可用時進行處理,而不需要等待所有數據都準備好。這對於處理大量數據或需要等待用戶輸入的情況非常有用。
其中
subscription = stream?.listen((event) {
setState(() {
lastNumber = event;
});
subscription?.onDone(() {
print('OnDone was called');
});
});
這段 Dart 程式碼是在設定一個 Stream 的監聽器。當 Stream 中有新的事件(在這個情況下,事件是一個數字)時,這個監聽器會被調用。
`stream?.listen((event) {...})` 是在設定監聽器。當 Stream 中有新的事件時,會調用這個函數,並將新的事件作為參數傳遞給它。
在你的回調函數中,你使用 `setState` 方法來更新 `lastNumber` 的值。這將觸發界面的重新渲染,並將新的數字顯示在界面上。
此外,你還設定了一個 `onDone` 監聽器,當 Stream 完成時(也就是說,當 Stream 中沒有更多的事件時),這個監聽器會被調用。在你的 `onDone` 監聽器中,你打印了一條消息,表示 Stream 已經完成。
最後,`stream?.listen(...)` 返回一個 `StreamSubscription` 對象,你將它存儲在 `subscription` 變量中。你可以使用這個 `StreamSubscription` 對象來控制對 Stream 的監聽,例如,你可以使用它來暫停、恢復或取消監聽。
關於StreamSubscription¶
在 Dart 中,`StreamSubscription` 是用來監聽 Stream 的。當你對一個 Stream 調用 `listen` 方法時,它會返回一個 `StreamSubscription` 對象。
`StreamSubscription` 提供了一些方法來控制對 Stream 的監聽:
- `pause`:暫停接收 Stream 的事件。
- `resume`:恢復接收 Stream 的事件。
- `cancel`:停止接收 Stream 的事件並取消訂閱。
此外,`StreamSubscription` 還有一些屬性可以讓你獲取有關訂閱的信息,例如 `isPaused` 可以告訴你訂閱是否已經暫停。
所以,`subscription` 在你的程式碼中可能是用來監聽 Stream 並控制對 Stream 的監聽的。例如,你可能會使用 `subscription` 來暫停或恢復接收 Stream 的事件,或者在不再需要 Stream 時取消訂閱。
Last update :
13 novembre 2024
Created : 13 novembre 2024
Created : 13 novembre 2024
