上下文
下面的代码代表了一种抽象形式,其中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/