Flutter - 未处理的异常:在 dispose() 后调用了 setState() AND _StreamBuilderBaseState
Flutter - 未处理的异常:在 dispose() 后调用了 setState() AND _StreamBuilderBaseState
当改变设备方向时,我遇到以下错误:
E/flutter (31741): [ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: setState() called after dispose(): _StreamBuilderBaseState
, AsyncSnapshot
>>#afadb(lifecycle state: defunct, not mounted)
E/flutter (31741): 如果您在不再出现在widget树中的widget的State对象上调用setState()(例如,其父widget不再在其构建中包含该widget),则会发生此错误。当代码从计时器或动画回调中调用setState()时,可能会发生此错误。
E/flutter (31741): 首选解决方案是在dispose()回调中取消计时器或停止监听动画。另一种解决方案是在调用setState()之前检查此对象的“mounted”属性,以确保对象仍然在树中。
E/flutter (31741): 如果因为其他对象保留对该State对象的引用而在调用setState(),则此错误可能表示内存泄漏。为避免内存泄漏,在dispose()期间考虑断开与该对象的引用。
E/flutter (31741): #0 State.setState.
E/flutter (31741): #1 State.setState (package:flutter/src/widgets/framework.dart:1239:6)
E/flutter (31741): #2 _StreamBuilderBaseState._subscribe.
E/flutter (31741): #3 _StartWithValueStream.listen.
E/flutter (31741): #4 _rootRun (dart:async/zone.dart:1182:47)
E/flutter (31741): #5 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter (31741): #6 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter (31741): #7 _CustomZone.bindCallbackGuarded.
E/flutter (31741): #8 _rootRun (dart:async/zone.dart:1190:13)
E/flutter (31741): #9 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter (31741): #10 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter (31741): #11 _CustomZone.bindCallbackGuarded.
E/flutter (31741): #12 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (31741): #13 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter (31741):
现在,我知道关于if (mounted) setState修复,但问题是我在我的应用程序中没有使用setState
,因为我使用bloclibrary
。
此外,根据错误信息,我可以看到StreamBuilder
,这是以下代码片段引发问题的唯一线索:>
...
@override
Widget build(BuildContext context) {
return StreamBuilder>(
stream: RepositoryProvider.of
.scheduledActivitiesDao
.watchActivitiesByPlant(widget.plantId),
builder: (context, snapshot) {
if (snapshot.hasError) print('>>>> DB error - ${snapshot.error}');
if (!snapshot.hasData) return ProgressIndicatorWidget();
return Text('items = ${snapshot.data.length}');
},
);
}
...
对于上面的代码,有两个注意事项:
- 上面我发布的
build
函数所在的Widget是StatefulWidget
,但即使我将其重构为StatelessWidget
,仍然会出现相同的错误 - 这个问题只会在我从横向切换到纵向模式时出现。
Flutter - Unhandled Exception: setState() called after dispose() AND _StreamBuilderBaseState
最近在使用Flutter开发过程中,遇到了一个问题:Unhandled Exception: setState() called after dispose() AND _StreamBuilderBaseState。经过排查,发现该问题的出现原因是每次build方法被调用时,都会创建一个新的Stream对象。
为了解决这个问题,我进行了代码重构,具体步骤如下:
1. 添加一个Stream对象_stream,用于存储数据流。
Stream> _stream;
2. 在didChangeDependencies方法中设置_stream的值。
void didChangeDependencies() {
super.didChangeDependencies();
_stream = RepositoryProvider.of
.scheduledActivitiesDao
.watchActivitiesByPlant(widget.plantId);
}
3. 将原先的代码替换为使用_stream的方式。
stream: _stream,
通过以上步骤的重构,成功解决了Unhandled Exception: setState() called after dispose() AND _StreamBuilderBaseState的问题。现在在调用setState方法时不会引发错误,同时也能正常使用StreamBuilder进行数据流的构建。
希望以上的解决方法对于其他遇到类似问题的开发者有所帮助。如果您在Flutter开发中遇到了类似的错误,可以尝试按照上述步骤进行代码重构,看看是否能够解决问题。祝您的Flutter开发之路顺利!