FirebaseAnimatedList in TabBarView : setState called after dispose

578 views
Skip to first unread message

sbes...@gmail.com

unread,
Oct 16, 2017, 5:56:40 PM10/16/17
to Flutter Dev

Hi All,

I inserted a 

body: new TabBarView(
controller: _tabController,
children: [
_buildRecordTab(),
_buildMemoList(),
new Center(
child: new Text("Settings"), // TODO : build settings screen
),
]),


with

Widget _buildMemoList(){
  return new Column(
    children: [
      new Flexible(
      child: new FirebaseAnimatedList(
        query
          : reference,
        sort: (a, b) =>
          b.key.compareTo(a.key
          ),
        padding: new EdgeInsets.all(8.0
        ),
        reverse: false,
        itemBuilder:
          (_, DataSnapshot snapshot, Animation<double> animation) {
          return new MnemoItem(snapshot: snapshot, animation: animation);
        })
      ),
     ]
    );
}

Whenever the tab isn't visible, the FirebaseAnimatedList must be disposed, yet its setState is still called:
  
setState() called after dispose(): FirebaseAnimatedListState#a417b(lifecycle state: defunct, not mounted)
This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. 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.<anonymous closure> (package:flutter/src/widgets/<…>

Is there a way to dispose of the list's observers ?

Thanks in advance
Serge

sbes...@gmail.com

unread,
Oct 16, 2017, 6:19:19 PM10/16/17
to Flutter Dev
I should probably mention that I tweaked the firebase_animated_list.dart this way (added last line)

void _onChildAdded(int index, DataSnapshot snapshot) {
if (!_loaded) {
return; // AnimatedList is not created yet
}
if (mounted) _animatedListKey.currentState.insertItem(index, duration: widget.duration);
}

Ian Hickson

unread,
Oct 16, 2017, 7:29:03 PM10/16/17
to sbes...@gmail.com, Flutter Dev
What's the rest of the stack trace like?

--
You received this message because you are subscribed to the Google Groups "Flutter Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flutter-dev...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--

--
Ian Hickson

😸

sbes...@gmail.com

unread,
Oct 18, 2017, 4:22:30 PM10/18/17
to Flutter Dev
Hi Ian,

Here is the stack trace. Strangely enough, it was called 3 times for a single update in the DB.

2017-10-18 22:16:13.691781+0200 Runner[27448:431115] [VERBOSE-2:dart_error.cc(16)] Unhandled exception:

setState() called after dispose(): FirebaseAnimatedListState#f3cf5(lifecycle state: defunct, not mounted)

This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. 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.<anonymous closure> (package:flutter/src/widgets/framework.dart:1144)

#1      State.setState (package:flutter/src/widgets/framework.dart:1161)

#2      FirebaseAnimatedListState._onChildChanged (package:firebase_database/ui/firebase_animated_list.dart:185)

#3      FirebaseSortedList._onChildChanged (package:firebase_database/ui/firebase_sorted_list.dart:99)

#4      _RootZone.runUnaryGuarded (dart:async/zone.dart:1314)

#5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:330)

#6      _DelayedData.perform (dart:async/stream_impl.dart:578)

#7      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:694)

#8      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:654)

#9      _microtaskLoop (dart:async/schedule_microtask.dart:41)

#10     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)

2017-10-18 22:16:13.702582+0200 Runner[27448:431115] [VERBOSE-2:dart_error.cc(16)] Unhandled exception:

setState() called after dispose(): FirebaseAnimatedListState#c0cb6(lifecycle state: defunct, not mounted)

This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. 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.<anonymous closure> (package:flutter/src/widgets/framework.dart:1144)

#1      State.setState (package:flutter/src/widgets/framework.dart:1161)

#2      FirebaseAnimatedListState._onChildChanged (package:firebase_database/ui/firebase_animated_list.dart:185)

#3      FirebaseSortedList._onChildChanged (package:firebase_database/ui/firebase_sorted_list.dart:99)

#4      _RootZone.runUnaryGuarded (dart:async/zone.dart:1314)

#5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:330)

#6      _DelayedData.perform (dart:async/stream_impl.dart:578)

#7      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:694)

#8      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:654)

#9      _microtaskLoop (dart:async/schedule_microtask.dart:41)

#10     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)

2017-10-18 22:16:13.710405+0200 Runner[27448:431115] [VERBOSE-2:dart_error.cc(16)] Unhandled exception:

setState() called after dispose(): FirebaseAnimatedListState#f3cf5(lifecycle state: defunct, not mounted)

This error happens if you call setState() on a State object for a widget that no longer appears in the widget tree (e.g., whose parent widget no longer includes the widget in its build). This error can occur when code calls setState() from a timer or an animation callback. 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.<anonymous closure> (package:flutter/src/widgets/framework.dart:1144)

#1      State.setState (package:flutter/src/widgets/framework.dart:1161)

#2      FirebaseAnimatedListState._onValue (package:firebase_database/ui/firebase_animated_list.dart:194)

#3      FirebaseSortedList._onValue (package:firebase_database/ui/firebase_sorted_list.dart:103)

#4      _RootZone.runUnaryGuarded (dart:async/zone.dart:1314)

#5      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:330)

#6      _DelayedData.perform (dart:async/stream_impl.dart:578)

#7      _StreamImplEvents.handleNext (dart:async/stream_impl.dart:694)

#8      _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:654)

#9      _microtaskLoop (dart:async/schedule_microtask.dart:41)

#10     _startMicrotaskLoop (dart:async/schedule_microtask.dart:50)

2017-10-18 22:16:13.718848+0200 Runner[27448:431115] [VERBOSE-2:dart_error.cc(16)] Unhandled exception:

setState() called after dispose(): FirebaseAnimatedListState#c0cb6(lifecycle state: defunct, not mounted)

Ian Hickson

unread,
Oct 18, 2017, 8:10:51 PM10/18/17
to sbes...@gmail.com, Flutter Dev
Well what's going on is that your FirebaseAnimatedList has been removed from the widget tree, yet it was still called. Maybe it doesn't properly unregister its listeners when dispose() is called?

If you can reproduce this in a small test app, please file a bug, it might be a bug with the plugin.

--
You received this message because you are subscribed to the Google Groups "Flutter Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flutter-dev...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--

--
Ian Hickson

😸
Reply all
Reply to author
Forward
0 new messages