flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
162.3k stars 26.67k forks source link

Updating DefaultTabController with length greater than 2 in a StatefulWidget, then tapping the last tab, results in "setState() called after dispose()" exception #147788

Closed ronjb closed 2 weeks ago

ronjb commented 2 weeks ago

Steps to reproduce

  1. Run the included sample app in web or any platform.
  2. Tap the + fab to create three tabs.
  3. Tap the last tab, and exception will be thrown.

Expected results

Expected exception to not be thown.

Actual results

Exception was thrown. See the Logs for details.

Code sample

Code sample ```dart import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp(home: MyHomePage())); } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { int _counter = 0; void _add(int i) => setState(() => _counter += i); @override Widget build(BuildContext context) { final intList = [for (var i = 0; i < _counter; i++) i]; return Scaffold( appBar: AppBar(title: Text('TabController test with $_counter tabs')), body: intList.isEmpty ? const Center(child: Text('Tap + 3 times to create 3 tabs, then tap the last tab.')) : DefaultTabController( length: intList.length, child: Column( children: [ TabBar(tabs: intList.map((i) => Tab(text: 'Tab $i')).toList()), Expanded( child: TabBarView( children: intList.map((i) => Center(child: Text('View $i'))).toList()), ) ], ), ), floatingActionButton: Row( mainAxisSize: MainAxisSize.min, children: [ FloatingActionButton(onPressed: () => _add(1), child: const Icon(Icons.add)), const SizedBox(width: 16), FloatingActionButton(onPressed: () => _add(-1), child: const Icon(Icons.remove)), ], ), ); } } ```

Screenshots or Video

Screenshots / Video demonstration [Upload media here]

Logs

Logs ```console Launching lib/main.dart on Chrome in debug mode... This app is linked to the debug service: ws://127.0.0.1:53608/FENKUkPN7nc=/ws Debug service listening on ws://127.0.0.1:53608/FENKUkPN7nc=/ws Connecting to VM Service at ws://127.0.0.1:53608/FENKUkPN7nc=/ws ══╡ EXCEPTION CAUGHT BY ANIMATION LIBRARY ╞═════════════════════════════════════════════════════════ The following assertion was thrown while notifying listeners for AnimationController: setState() called after dispose(): _AnimatedState#e0e73(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(). When the exception was thrown, this was the stack: dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3 throw_ packages/flutter/src/widgets/framework.dart 1167:9 packages/flutter/src/widgets/framework.dart 1201:14 setState packages/flutter/src/widgets/transitions.dart 129:5 [_handleChange] packages/flutter/src/animation/listener_helpers.dart 161:11 notifyListeners packages/flutter/src/animation/animation_controller.dart 865:5 [_tick] packages/flutter/src/scheduler/ticker.dart 258:12 [_tick] packages/flutter/src/scheduler/binding.dart 1386:7 [_invokeFrameCallback] packages/flutter/src/scheduler/binding.dart 1233:11 dart-sdk/lib/_internal/js_dev_runtime/private/linked_hash_map.dart 21:7 forEach packages/flutter/src/scheduler/binding.dart 1231:16 handleBeginFrame packages/flutter/src/scheduler/binding.dart 1148:5 [_handleBeginFrame] lib/_engine/engine/platform_dispatcher.dart 1361:5 invoke1 lib/_engine/engine/platform_dispatcher.dart 237:5 invokeOnBeginFrame lib/_engine/engine/initialization.dart 176:36 dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 550:37 _checkAndCall dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 555:39 dcall The AnimationController notifying listeners was: AnimationController#fca21(▶ 0.077) ════════════════════════════════════════════════════════════════════════════════════════════════════ Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) Another exception was thrown: setState() called after dispose(): _AnimatedState#e0e73(lifecycle state: defunct, not mounted) ```

Flutter Doctor output

Doctor output ```console √ ~/Development/flutter_app_tests 🌀 flutter doctor -v [✓] Flutter (Channel stable, 3.19.6, on macOS 14.4.1 23E224 darwin-arm64, locale en-US) • Flutter version 3.19.6 on channel stable at /Users/ronbooth/Development/flutter • Upstream repository https://github.com/flutter/flutter.git • Framework revision 54e66469a9 (2 weeks ago), 2024-04-17 13:08:03 -0700 • Engine revision c4cd48e186 • Dart version 3.3.4 • DevTools version 2.31.1 [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0) • Android SDK at /Users/ronbooth/Library/Android/sdk • Platform android-34, build-tools 34.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160) • All Android licenses accepted. [✓] Xcode - develop for iOS and macOS (Xcode 15.3) • Xcode at /Applications/Xcode.app/Contents/Developer • Build 15E204a • CocoaPods version 1.15.2 [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome [✓] Android Studio (version 2023.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 17.0.10+0-17.0.10b1087.21-11572160) [✓] VS Code (version 1.88.1) • VS Code at /Applications/Visual Studio Code.app/Contents • Flutter extension version 3.88.0 [✓] Connected device (4 available) • Ron’s iPad Pro (mobile) • 00008103-00084486018A001E • ios • iOS 17.4.1 21E236 • iPad mini (6th generation) (mobile) • AEABF899-FFD4-41D8-9757-0320607C6F2B • ios • com.apple.CoreSimulator.SimRuntime.iOS-16-4 (simulator) • macOS (desktop) • macos • darwin-arm64 • macOS 14.4.1 23E224 darwin-arm64 • Chrome (web) • chrome • web-javascript • Google Chrome 124.0.6367.119 [✓] Network resources • All expected network resources are available. • No issues found! √ ~/Development/flutter_app_tests 🌀 ```
ronjb commented 2 weeks ago

Here's a link to the sample app for reproducing the bug in DartPad: DartPad example

ronjb commented 2 weeks ago

Looks like this bug is a duplicate of https://github.com/flutter/flutter/issues/144087, which has been fixed, just hasn't made it to stable yet.

github-actions[bot] commented 2 days ago

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.