-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Closed
Labels
c: crashStack traces logged to the consoleStack traces logged to the consolef: material designflutter/packages/flutter/material repository.flutter/packages/flutter/material repository.f: 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 onr: 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.
Metadata
Metadata
Assignees
Labels
c: crashStack traces logged to the consoleStack traces logged to the consolef: material designflutter/packages/flutter/material repository.flutter/packages/flutter/material repository.f: 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 onr: 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