flutter - 多个访问同一流

标签 flutter dart stream dart-stream

上下文
下面的代码代表了一种抽象形式,其中MyClass是某种下载管理器。

import 'dart:async';

Future<void> main() async {
  MyClass().test().listen((v) => print('t1: $v')).onError(print);
  final commomClass = MyClass();
  commomClass.test().listen((v) => print('t2: $v')).onError(print);
  commomClass.test().listen((v) => print('t3: $v')).onError(print);
}

class MyClass {
  bool _isDownloadInProgress = false;
  int _i = 0;
  StreamController<int> _sc;
  
  Stream<int> test() async* {
    if (_isDownloadInProgress) {
      throw Exception('Download already in progress');
    } else {
      _sc = StreamController<int>();
    }
    
    Timer.periodic(
      const Duration(seconds: 1),
      (t) {
        if (_i == 4) {
          _isDownloadInProgress = false;
          _i = 0;
          _sc.close();
          t.cancel();
        } else {
          _sc.add(_i++);
        }
      },
    );

    yield* _sc.stream;
  }
}
问题
我希望执行此代码后,它将生成值t1和t2,而输出t3将仅生成一次“下载已在进行中”。例如:
t1: 0
t2: 0
t3: Download already in progress
t1: 1
t2: 1
t1: 2
t2: 2
t1: 3
t2: 3
但是它会输出所有四个 t1值,八个 t3值和 no '下载已在进行中'消息:
t1: 0
t3: 0
t3: 1
t1: 1
t3: 2
t3: 3
t1: 2
t3: 0
t1: 3
t3: 1
t3: 2
t3: 3
对我来说,t1值将正确输出,t2也将正确输出,t3将输出“下载已进行中”消息,因为当所有内容都异步运行时,它将试图“下载”已存在的内容正在下载(因为在test()的同一实例上调用了MyClass方法)。
我想念什么?

最佳答案

对于初学者,您的代码永远不会将_isDownloadInProgress设置为true,因此没有理由会出现“下载已在进行中”。
这实际上是导致第二个错误的原因。当您调用t3 listen时,由于_isDownloadInProgress始终为false,因此除了将新的_sc放入队列之外,这还导致Timer.periodic被覆盖。每个计时器触发时,它都引用_sc,现在它是包含t3 listen的那个,因此您最终得到两个计时器,将事件推送到同一流 Controller ,这就是为什么您看到t3事件翻倍的原因。
只需在实例化计时器之前设置_isDownloadInProgress = true就足以获得预期的结果:

class MyClass {
  bool _isDownloadInProgress = false;
  int _i = 0;
  StreamController<int> _sc;
  
  Stream<int> test() async* {
    if (_isDownloadInProgress) {
      throw Exception('Download already in progress');
    } else {
      _sc = StreamController<int>();
    }
    
    _isDownloadInProgress = true; // Add this line
    Timer.periodic(
      const Duration(seconds: 1),
      (t) {
        if (_i == 4) {
          _isDownloadInProgress = false;
          _i = 0;
          _sc.close();
          t.cancel();
        } else {
          _sc.add(_i++);
        }
      },
    );

    yield* _sc.stream;
  }
}
结果:
Exception: Download already in progress
t1: 0
t2: 0
t1: 1
t2: 1
t1: 2
t2: 2
t1: 3
t2: 3

关于flutter - 多个访问同一流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63586452/

相关文章:

compiler-errors - Dart 编辑器在使用 "part of"时停止突出显示错误

flutter - 将Flutter应用复制到新项目时要复制哪些文件夹?

c# - 使用utf16编码将字符串写入流

flutter - 类型 'TextEditingController' 不是类型转换中类型 'int' 的子类型

flutter - 如何将数据从方法_callLogs传递到正文并进行打印?

laravel - Flutter 中出现 401 未经授权的错误,但在 Postman 中工作正常

flutter - Dart 中的 int 类型是值类型还是引用类型?

stream - 如何制作长按按键时触发的KeyboardEvent流? ( Dart )

c++ - 自动替换stringstream中的字符

json - 将多行字符串从文本字段保存到 JSON 文件