Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[Sensors] Fix:avoid calling setState() when mounted is false. #2361

Closed
wants to merge 1 commit into from

Conversation

Notzuonotdied
Copy link

It is an error to call [setState] unless [mounted] is true.

Description

The preferred solution is to cancel the timer or stop listening to the animation in the dispose() callback. Another solution is to check the "mounted" property of this object before calling setState() to ensure the object is still in the tree.

This error might indicate a memory leak if setState() is being called because another object is retaining a reference to this State object after it has been removed from the tree. To avoid memory leaks, consider breaking the reference to this object during dispose().

#0 State.setState. (package:flutter/src/widgets/framework.dart:1105:9)
#1 State.setState (package:flutter/src/widgets/framework.dart:1140:6)
#2 SnakeState.initState. (package:.../qy_sensors/snake.dart:77:7) // setState()
#3 _rootRunUnary (dart:async/zone.dart:1132:38)
#4 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#5 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
#6 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
#7 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
#8 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:132:11)
#9 _MapStream._handleData (dart:async/stream_pipe.dart:232:10)
#10 _ForwardingStreamSubscription._handleData (dart:async/stream_pipe.dart:164:13)
#11 _rootRunUnary (dart:async/zone.dart:1132:38)
#12 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#13 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
#14 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
#15 _DelayedData.perform (dart:async/stream_impl.dart:591:14)
#16 _StreamImplEvents.handleNext (dart:async/stream_impl.dart:707:11)
#17 _PendingEvents.schedule. (dart:async/stream_impl.dart:667:7)
#18 _rootRun (dart:async/zone.dart:1120:38)
#19 _CustomZone.run (dart:async/zone.dart:1021:19)
#20 _CustomZone.runGuarded (dart:async/zone.dart:923:7)
#21 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:963:23)
#22 _rootRun (dart:async/zone.dart:1124:13)
#23 _CustomZone.run (dart:async/zone.dart:1021:19)
#24 _CustomZone.runGuarded (dart:async/zone.dart:923:7)
#25 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:963:23)
#26 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
#27 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)

It is an error to call [setState] unless [mounted] is true.
Copy link
Contributor

@ened ened left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Notzuonotdied thank you for the PR, would you like to continue working on it? There are few comments which would be great if you can include them.

Please also follow the standard PR issue template (we have a check list etc).

Finally, please add an entry to the change log and increment the version (+1).

@@ -73,12 +73,14 @@ class SnakeState extends State<Snake> {
void initState() {
super.initState();
accelerometerEvents.listen((AccelerometerEvent event) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The return value of listen is a StreamSubscription<AccelerometerEvent>. That should move into a _accelerometerEventSubscription field. Please cancel() it in the dispose method.

@@ -73,12 +73,14 @@ class SnakeState extends State<Snake> {
void initState() {
super.initState();
accelerometerEvents.listen((AccelerometerEvent event) {
if (!mounted) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add { and } to make things a bit cleared in the sample

setState(() {
acceleration = event;
});
});

Timer.periodic(const Duration(milliseconds: 200), (_) {
if (!mounted) return;
Copy link
Contributor

@ened ened Dec 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can actually replace the _ with timer and then cancel the timer as well, when not mounted.

Perhaps keep the timer in a _timer field and cancel in the dispose method as above. Sorry.

@cyanglaz cyanglaz changed the title Fix:avoid calling setState() when mounted is false. [Sensors] Fix:avoid calling setState() when mounted is false. Jul 22, 2020
@stuartmorgan
Copy link
Contributor

Closing due to lack of updates.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants