Flutter之Stream、StreamController的使用(二)

下面的例子展示了如何使用 StreamControllerFlutter 應(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)變化。下面的示例中,我們將使用一個 StatelessWidgetStreamController來實現(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)管理方法(如 GetXRiverpod)來更安全地管理流的生命周期。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容