为何无法在stopSending()中取消StreamSubscription?报错未初始化
问题分析:手动调用stopSending触发LateInitializationError的原因
问题代码
import 'dart:async'; import 'dart:math'; class TestService { Random random = Random(); StreamController<double> streamController = StreamController<double>(); StreamController<double> streamController2 = StreamController<double>(); late StreamSubscription<double> streamSubscription; late StreamSubscription<double> streamSubscription2; void startSending() { streamController.addStream(Stream.periodic(Duration(seconds: 1), (count) => count.toDouble()).take(5)); streamSubscription = streamController.stream.listen((event) { print('event 2:$event'); }); } void stopSending() { streamSubscription.cancel(); streamController.close(); } void startAndStop(){ streamController.addStream(Stream.periodic(Duration(seconds: 1), (count) => count.toDouble())); streamSubscription = streamController.stream.listen((event) { print('event 2:$event'); }); Future.delayed(Duration(seconds: 10),() { streamSubscription.cancel(); streamController.close(); },); } void dispose() { streamController.close(); streamController2.close(); } }
问题描述
通过手势触发调用stopSending()方法取消streamSubscription时,抛出LateInitializationError提示字段未初始化;但调用startAndStop()方法时,能正常在延迟回调中取消订阅,请问原因是什么?
核心原因
触发错误的本质是:调用stopSending()时,用late修饰的streamSubscription变量从未被赋值初始化。
场景对比分析
startAndStop()正常执行的原因:该方法内部先调用streamController.stream.listen()获取订阅对象,并完成streamSubscription的赋值,之后延迟10秒的回调才去调用cancel(),此时变量已经完成初始化,不会触发错误。- 手势调用
stopSending()出错的原因:手势触发操作时,大概率还没调用过startSending()或startAndStop()方法,导致streamSubscription始终处于未初始化状态,直接访问该变量就触发了Dart对late变量的未初始化检查。
修复方案
方案1:使用可空类型替代late
将streamSubscription改为可空类型,避免强制初始化要求:
StreamSubscription<double>? streamSubscription;
方案2:在stopSending()中增加空判断
调用cancel()前先检查变量是否已初始化,避免空访问:
void stopSending() { streamSubscription?.cancel(); // 使用?.操作符,仅当变量非空时执行cancel streamController.close(); }
方案3:确保调用顺序(不推荐)
在业务逻辑中强制要求必须先调用startSending()或startAndStop(),才能调用stopSending()。但这种方案依赖业务逻辑约束,不如前两种方案安全。
内容的提问来源于stack exchange,提问作者RJ84
相关产品推荐
相关产品推荐

