Repository navigation
TabBarView crashes when switching index before layout #86222
Copy link
Copy link
Closed
Labels
c: crashStack traces logged to the consoleStack traces logged to the consolef: routesNavigator, Router, and related APIs.Navigator, Router, and related APIs.found in release: 2.2Found to occur in 2.2Found to occur in 2.2frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: material_uimaterial_ui package in flutter/packagesmaterial_ui package in flutter/packagesr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-designOwned by Design Languages teamOwned by Design Languages teamtriaged-designTriaged by Design Languages teamTriaged by Design Languages team
Description
TabBarView crashes if you try to switch index before it's been laid out.
Steps to Reproduce
- Create a
TabBarViewwith aTabController - Try to switch tabs programatically using the controller - but before the
TabBarViewhas been laid out
Tested on stable 2.2.3 and dev 2.4.0-0.0.pre.
Repro
Run this repro and click the button.
The reason the TabBarView hasn't been laid out is due to using Navigator 2.0 - imagine that this state has been restored on startup, with two pages already in the stack.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
// This allows switching tabs from anywhere
class NavigationManager extends ChangeNotifier {
int _index = 0;
int get index => _index;
set index(int newIndex) {
_index = newIndex;
notifyListeners();
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(home: HomePage());
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final _navManager = NavigationManager();
@override
Widget build(BuildContext context) {
return Scaffold(
body: Navigator(
onPopPage: (route, result) {
return route.didPop(result);
},
pages: [
MaterialPage(child: TabPage(navManager: _navManager)),
MaterialPage(child: SubPage(navManager: _navManager)),
],
),
);
}
}
class TabPage extends StatefulWidget {
final NavigationManager navManager;
TabPage({required this.navManager});
@override
_TabPageState createState() => _TabPageState();
}
class _TabPageState extends State<TabPage> with SingleTickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 2, vsync: this);
widget.navManager.addListener(() {
// Global navigation has updated, change controller
// This is where the crash occurs, because the TabBarView has not
// yet been laid out
_tabController.index = widget.navManager.index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: TabBarView(
controller: _tabController,
children: [
Scaffold(body: Text('One')),
Scaffold(body: Text('Two')),
],
),
);
}
}
class SubPage extends StatelessWidget {
final NavigationManager navManager;
SubPage({required this.navManager});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: ElevatedButton(
onPressed: () {
// Switch the tab
navManager.index = 1;
},
child: Text('Change tab'),
),
),
);
}
}Expected results: On eventually showing the TabBarView, the index is correct.
Actual results: Crashes due to viewportDimension being null.
Logs
[ +1 ms] An Observatory debugger and profiler on macOS is available at: http://127.0.0.1:51581/6xepRBr4z90=/
[ +110 ms] Activating Dart DevTools...
[+1585 ms] [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: Null check operator used on a null value
[ ] #0 ScrollPosition.viewportDimension (package:flutter/src/widgets/scroll_position.dart:172:53)
[ ] #1 _PagePosition.getPixelsFromPage (package:flutter/src/widgets/page_view.dart:382:19)
[ ] #2 PageController.animateToPage (package:flutter/src/widgets/page_view.dart:197:16)
[ ] #3 _TabBarViewState._warpToCurrentIndex (package:flutter/src/material/tabs.dart:1417:29)
[ ] #4 _TabBarViewState._handleTabControllerAnimationTick (package:flutter/src/material/tabs.dart:1403:7)
[ ] #5 AnimationLocalListenersMixin.notifyListeners (package:flutter/src/animation/listener_helpers.dart:136:19)
[ ] #6 AnimationController.value= (package:flutter/src/animation/animation_controller.dart:366:5)
[ ] #7 TabController._changeIndex (package:flutter/src/material/tab_controller.dart:232:29)
[ ] #8 TabController.index= (package:flutter/src/material/tab_controller.dart:250:5)
[ ] #9 _TabPageState.initState.<anonymous closure> (package:tab_crash/main.dart:70:22)
[ ] #10 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:243:25)
[ ] #11 NavigationManager.index= (package:tab_crash/main.dart:13:5)
[ ] #12 SubPage.build.<anonymous closure> (package:tab_crash/main.dart:101:24)
[ ] #13 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:989:21)
[ ] #14 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
[ ] #15 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:607:11)
[ ] #16 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:296:5)
[ ] #17 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:230:7)
[ ] #18 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:475:9)
[ ] #19 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:93:12)
[ ] #20 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:138:9)
[ ] #21 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:397:8)
[ ] #22 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:136:18)
[ ] #23 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:122:7)
[ ] #24 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:439:19)
[ ] #25 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:419:22)
[ ] #26 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:287:11)
[ ] #27 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:374:7)
[ ] #28 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:338:5)
[ ] #29 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:296:7)
[ ] #30 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:279:7)
[ ] #31 _rootRunUnary (dart:async/zone.dart:1370:13)
[ ] #32 _CustomZone.runUnary (dart:async/zone.dart:1265:19)
[ ] #33 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1170:7)
[ ] #34 _invoke1 (dart:ui/hooks.dart:182:10)
[ ] #35 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:282:7)
[ ] #36 _dispatchPointerDataPacket (dart:ui/hooks.dart:96:31)
[+3413 ms] Activating Dart DevTools... (completed in 5.0s)
[ +562 ms] The Flutter DevTools debugger and profiler on macOS is available at: http://127.0.0.1:9104?uri=http%3A%2F%2F127.0.0.1%3A51581%2F6xepRBr4z90%3D%2F
No issues found! (ran in 1.6s)
[✓] Flutter (Channel stable, 2.2.3, on macOS 11.4 20F71 darwin-x64, locale en-FI)
• Flutter version 2.2.3 at /Users/tom/fvm/versions/stable
• Framework revision f4abaa0735 (9 days ago), 2021-07-01 12:46:11 -0700
• Engine revision 241c87ad80
• Dart version 2.13.4
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
• Android SDK at /Users/tom/Library/Android/sdk
• Platform android-30, build-tools 30.0.2
• ANDROID_HOME = /Users/tom/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 11.0.8+10-b944.6916264)
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 12.5.1, Build version 12E507
• CocoaPods version 1.10.1
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.2)
• 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 11.0.8+10-b944.6916264)
[✓] VS Code (version 1.58.0)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.24.0
[✓] Connected device (2 available)
• macOS (desktop) • macos • darwin-x64 • macOS 11.4 20F71 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 91.0.4472.114
! Doctor found issues in 1 category.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
c: crashStack traces logged to the consoleStack traces logged to the consolef: routesNavigator, Router, and related APIs.Navigator, Router, and related APIs.found in release: 2.2Found to occur in 2.2Found to occur in 2.2frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onp: material_uimaterial_ui package in flutter/packagesmaterial_ui package in flutter/packagesr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versionteam-designOwned by Design Languages teamOwned by Design Languages teamtriaged-designTriaged by Design Languages teamTriaged by Design Languages team
Activity
darshankawar commentedon Jul 12, 2021
Verified this on latest stable and I see the same behavior.
console error log
flutter doctor -v
victor-tinoco commentedon Aug 10, 2023
@darshankawar wasn't it addressed by this fix?
pschaffl commentedon Jan 3, 2024
Possible regression error (stable 3.16.5, web).
Error log
Workaround
Fix PageController throws when changing page before viewPortDimension…
Fix PageController throws when changing page before viewPortDimension…
Fix PageController throws when changing page before viewPortDimension…
github-actions commentedon Aug 21, 2024
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 -vand a minimal reproduction of the issue.Fix PageController throws when changing page before viewPortDimension…