You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter应用Stream监听失效问题:如何修复数据流传递?

问题根源与解决方案

你的代码核心问题是多次创建了DatabaseHandler的独立实例,导致监听流的实例和发送数据的实例完全不是同一个对象,两者的StreamController相互独立,所以监听器收不到任何数据。

具体问题点

  • 在initState里调用DatabaseHandler()创建了一个实例,监听它的流
  • 在Timer回调里又调用DatabaseHandler()创建了另一个全新的实例,调用它的startStream发送数据
  • 两个实例的_testStreamController完全分离,数据根本没发到你监听的那个流上

修复方案:使用单例模式确保全局唯一实例

修改DatabaseHandler为单例,保证整个应用中只会存在一个实例,这样生产者和消费者用的是同一个流:

import 'package:flutter/material.dart';
import 'dart:async';

Future<void> main() async {
  runApp(const MyApp());

  Timer.periodic(
    const Duration(seconds: 4),
    (timer) {
      // 调用全局唯一实例
      DatabaseHandler().startStream();
    }
  );
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late StreamSubscription<int> _streamSubscription;

  @override
  void initState(){
    super.initState();
    // 监听全局唯一实例的流
    _streamSubscription = DatabaseHandler().testStream.listen((int i) {
      print('Received location marker $i');
    });
  }

  @override
  void dispose() {
    // 取消订阅避免内存泄漏
    _streamSubscription.cancel();
    // 关闭流控制器释放资源
    DatabaseHandler().closeStream();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('Hello World!'),
        ),
      ),
    );
  }
}

class DatabaseHandler{
  late StreamController<int> _testStreamController;
  Stream<int> get testStream => _testStreamController.stream;

  // 单例实现:全局唯一实例
  static final DatabaseHandler _instance = DatabaseHandler._internal();
  factory DatabaseHandler() => _instance;
  
  // 私有构造函数,防止外部创建新实例
  DatabaseHandler._internal() {
    _testStreamController = StreamController<int>();
    print('Stream initialized');
  }

  void startStream() async {
    for (int i = 1; i <= 5; i++) {
      _testStreamController.add(i);
      print('Added data: $i to stream');
    }
  }

  // 流关闭方法,释放资源
  void closeStream() {
    _testStreamController.close();
  }
}

额外优化点

  1. 添加StreamSubscription并在dispose中取消订阅,避免内存泄漏
  2. 给DatabaseHandler添加流关闭方法,在应用退出或不再需要时释放资源
  3. 调整打印日志内容,让调试信息更清晰

内容的提问来源于stack exchange,提问作者RJrules64

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 01:55:21