下面的例子展示了如何使用 StreamController 在Flutter 應(yīng)用中創(chuàng)建一個簡單的計數(shù)器。其中用到了一個 StreamBuilder 組件來監(jiān)聽 StreamController 的流,并且在新數(shù)據(jù)發(fā)送到流時更新 UI。
import 'dart:async';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: CounterScreen(),
);
}
}
class CounterScreen extends StatefulWidget {
const CounterScreen({super.key});
@override
_CounterScreenState createState() => _CounterScreenState();
}
class _CounterScreenState extends State<CounterScreen> {
final StreamController<Map<String,dynamic>> _counterController = StreamController<Map<String,dynamic>>();
int _counter = 0;
Map<String,dynamic> _map = {"test":0};
@override
void dispose() {
_counterController.close(); // 關(guān)閉 StreamController 以釋放資源
super.dispose();
}
// 增加計數(shù)并將新值發(fā)送到流中
void _incrementCounter() {
_counter = _counter + 1;
_counterController.sink.add({"test":_counter});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Counter App")),
body: Center(
child: StreamBuilder<Map<String,dynamic>>(
stream: _counterController.stream,
initialData: _map, // 初始數(shù)據(jù)
builder: (context, snapshot) {
return Text(
'Counter Value: ${snapshot.data?["test"]}',
style: TextStyle(fontSize: 20),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
child: const Icon(Icons.add),
),
);
}
}
在 Flutter中,當(dāng)我們要管理可變狀態(tài)時,我們通常會使用 StatefulWidget。但是如果我們在 StatelessWidget 中使用外部狀態(tài)管理(比如 StreamController),我們也能夠在沒有 StatefulWidget 的情況下響應(yīng)狀態(tài)變化。下面的示例中,我們將使用一個 StatelessWidget 和 StreamController來實現(xiàn)計數(shù)器的功能:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final StreamController<Map<String, dynamic>> _counterController = StreamController<Map<String, dynamic>>.broadcast(); // 創(chuàng)建一個廣播控制器
int _counter = 0;
// 增加計數(shù)并將新值發(fā)送到流中
void incrementCounter() {
_counter = _counter + 1;
_counterController.sink.add({"test": _counter});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Counter App")),
body: Center(
child: StreamBuilder<Map<String, dynamic>>(
stream: _counterController.stream,
initialData: {"test": 0}, // 初始數(shù)據(jù)
builder: (context, snapshot) {
return Text(
'Counter Value: ${snapshot.data?["test"]}',
style: TextStyle(fontSize: 20),
);
},
),
),
floatingActionButton: FloatingActionButton(
onPressed: incrementCounter,
child: Icon(Icons.add),
),
),
);
}
}
在上面的代碼中,我們創(chuàng)建了一個廣播型的 StreamController(.broadcast()),這允許流有多個監(jiān)聽器。incrementCounter方法使計數(shù)器增加,并通過流控制器的 sink將新值發(fā)送到流中。
我們使用 StreamBuilder來監(jiān)聽流,并在流中的數(shù)據(jù)發(fā)生變化時重新構(gòu)建界面。
注意點
我們在這里沒有使用 dispose 來關(guān)閉 StreamController,因為在 StatelessWidget 中沒有 dispose 方法。在實際應(yīng)用中,請確保在適當(dāng)?shù)牡胤疥P(guān)閉流,以防止內(nèi)存泄漏。例如,你可以在頁面切換時關(guān)閉它,或使用其他狀態(tài)管理方法(如 GetX 或 Riverpod)來更安全地管理流的生命周期。