StreamSubscription官方解释:

订阅来自 [Stream] 的事件。当您使用 [Stream.listen] 监听 [Stream] 时,将返回 [StreamSubscription] 对象。

看上去还是比较晦涩,加上自己的理解就是:
订阅者(StreamSubscription)就一定会有生产者,不然就没意义了,订阅者订阅了就会收到东西(可能是正确的,有可能是错误的),可以针对这些东西做处理,当然也可以暂停订阅恢复订阅等,

onData()——处理接收到的正确的数据
onError()——处理接收到的错误
onDone()——当生产者不再生成数据(生产者调用close方法)时触发
isPaused——获取接收者状态,判断当前接收者是否暂停接收
pause()——暂停接收数据
resume()——恢复接收数据
cancel()——取消此订阅,不管生产者是否继续,将不再接收到信息

生产者(stream)可以生成东西,也可生成错误等;

listen()——返回订阅者对象,和订阅者产生关联的主要模式
add()——产生正确的数据
addError()——产生错误
isClosed——是否已经关闭
close()——关闭生产者(订阅者对象会触发onDone())

注:这两如何产生联系?
一般当调用streamlisten就会返回StreamSubscription对象;

代码例子:

  // 创建一个StreamController(生成数据)
  final StreamController<int> _streamController = StreamController<int>();

  // 声明一个StreamSubscription变量(订阅消费数据)
  late final StreamSubscription<int> _subscription;

  // 用于显示接收到的数据
  List<int> _receivedData = [];

  // 计时器,用于生成数据
  Timer? _timer;

  // 计数器
  int _counter = 0;

  @override
  void initState() {
    super.initState();

    // 初始化StreamSubscription
    _subscription = _streamController.stream.listen(
      // // 当接收到新数据时的回调
      // (data) {},
      // // 错误处理回调
      // onError: (error) {
      //   print('Stream错误: $error');
      // },
      // // 流完成时的回调
      // onDone: () {
      //   print('Stream已完成(close)——触发 onDone');
      // },
      null, // onData、onError、onDone 单独实现时,这儿传null就行
      // 设置是否在错误发生时取消订阅
      cancelOnError: false,
    );

    _subscription.onData((data) {
      setState(() {
        _receivedData.add(data);
        // 只保留最新的5个数据
        if (_receivedData.length > 5) {
          _receivedData.removeAt(0);
        }
      });
    });
    _subscription.onError((error) {
      print('Stream错误: $error');
    });

    _subscription.onDone(() {
      print('Stream已完成(close)——触发 onDone');
    });

    // 启动定时器,每秒向流中添加一个新数字
    _startTimer();
  }

  // 启动定时器方法
  void _startTimer() {
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      // 向流中添加数据
      _streamController.add(_counter++);
    });
  }

  // 暂停订阅
  void _pauseSubscription() {
    if (!_subscription.isPaused) {
      _subscription.pause();
    }
  }

  // 恢复订阅
  void _resumeSubscription() {
    if (_subscription.isPaused) {
      _subscription.resume();
    }
  }

  // 向流中添加错误
  void _addError() {
    _streamController.addError('这是一个测试错误');
  }

  // 关闭Stream
  void _closeStream() {
    // 停止定时器
    _timer?.cancel();
    _timer = null;

    // 关闭StreamController,这会触发onDone回调
    if (!_streamController.isClosed) {
      _streamController.close();
    }
  }

  @override
  void dispose() {
    // 取消定时器
    _timer?.cancel();

    // 先关闭StreamController
    _streamController.close();

    // 再取消流订阅
    _subscription.cancel();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('StreamSubscription示例')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('接收到的最新数据:'),
            const SizedBox(height: 10),
            Container(
              padding: const EdgeInsets.all(10),
              decoration: BoxDecoration(
                border: Border.all(color: Colors.grey),
                borderRadius: BorderRadius.circular(5),
              ),
              child: Text(
                _receivedData.isEmpty ? '尚未接收数据' : _receivedData.join(', '),
                style: const TextStyle(fontSize: 16),
              ),
            ),
            const SizedBox(height: 30),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                ElevatedButton(
                  onPressed: _pauseSubscription,
                  child: const Text('暂停订阅'),
                ),
                ElevatedButton(
                  onPressed: _resumeSubscription,
                  child: const Text('恢复订阅'),
                ),
                ElevatedButton(onPressed: _addError, child: const Text('添加错误')),
                ElevatedButton(
                  onPressed: _closeStream,
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.red,
                    foregroundColor: Colors.white,
                  ),
                  child: const Text('关闭Stream (触发onDone)'),
                ),
              ],
            ),
            const SizedBox(height: 50),
            const Text(
              'StreamSubscription说明:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 10),
            const Text(
              '1. StreamSubscription用于订阅数据流(Stream)\n'
              '2. 通过listen()方法创建订阅并处理数据\n'
              '3. 可以暂停(pause)和恢复(resume)数据接收\n'
              '4. 必须在不需要时取消(cancel)订阅以防止内存泄漏\n'
              '5. 在本例中,定时器每秒产生一个数字并发送到流中\n'
              '6. 使用上方按钮可以控制数据流的接收',
              style: TextStyle(fontSize: 14),
            ),
          ],
        ),
      ),
    );
  }

代码效果:


qngyun1029
980 声望15 粉丝