Skip to content

Hot reload doesn't recognize change in length in DefaultTabController #18686

Closed

Description

@zachjanicki

When updating the DefaultTabController from the tutorial to a length of 4 instead of 3 and reloading, Flutter doesn't recognize that the length value has changed.
This is the code:

import 'package:flutter/material.dart';

void main() => runApp(new HeadacheApp());

class HeadacheApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 4,
        child: Scaffold(
          appBar: AppBar(
            bottom: TabBar(
              tabs: [
                Tab(icon: Icon(Icons.directions_car)),
                Tab(icon: Icon(Icons.directions_transit)),
                Tab(icon: Icon(Icons.directions_bike)),
                Tab(icon: Icon(Icons.help)),
              ],
            ),
            title: Text('Tabs Demo'),
          ),
          body: TabBarView(
            children: [
              Icon(Icons.directions_car),
              Icon(Icons.directions_transit),
              Icon(Icons.directions_bike),
              Icon(Icons.help),
            ],
          ),
        ),
      ),
    );
  }
}

It gives the following error:

flutter: ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
flutter: The following assertion was thrown while handling a gesture:
flutter: 'package:flutter/src/material/tab_controller.dart': Failed assertion: line 112 pos 12: 'value >= 0
flutter: && (value < length || length == 0)': is not true.
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter:   https://github.com/flutter/flutter/issues/new
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #2      TabController._changeIndex (package:flutter/src/material/tab_controller.dart)
flutter: #3      TabController.animateTo (package:flutter/src/material/tab_controller.dart:164:5)
flutter: #4      _TabBarState._handleTap (package:flutter/src/material/tabs.dart:864:17)
flutter: #5      _TabBarState.build.<anonymous closure> (package:flutter/src/material/tabs.dart:939:21)
flutter: #6      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:494:14)
flutter: #7      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:549:30)
flutter: #8      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
flutter: #9      TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:161:9)
flutter: #10     TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:94:7)
flutter: #11     PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:315:9)
flutter: #12     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:73:12)
flutter: #13     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:11)
flutter: #14     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:143:19)
flutter: #15     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
flutter: #16     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
flutter: #17     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
flutter: #18     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
flutter: #19     _invoke1 (dart:ui/hooks.dart:134:13)
flutter: #20     _dispatchPointerDataPacket (dart:ui/hooks.dart:91:5)
flutter: (elided 2 frames from class _AssertionError)
flutter:
flutter: Handler: onTap
flutter: Recognizer:
flutter:   TapGestureRecognizer#8e887(debugOwner: GestureDetector, state: possible, won arena, finalPosition:
flutter:   Offset(329.3, 132.7), sent tap down)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════

I went into flutter/src/material/tab_controller.dart and printed the values of length and value which were both 3 instead of 3 and 4, which caused the exception to be raised. I was able to fix this by restarting the iPhone simulator and re-uploading the app.

Activity

  1. zoechi commented on Jun 22, 2018

    @zoechi
    Contributor
  2. zoechi commented on Jun 22, 2018

    @zoechi
    Contributor

    @zachjanicki
    Please add the output of flutter doctor

  3. cbracken commented on Jul 9, 2018

    @cbracken
    Member

    /cc @rmacnak-google who IIRC looked into similar issues in the past (specifically detecting and warning about changes that aren't reloaded).

  4. no-or-no commented on Jul 17, 2018

    @no-or-no

    similar issue!
    my code:

    import 'dart:async';
    import 'package:flutter/material.dart';
    
    void main() => runApp(new MaterialApp(
        home: new MyApp(),
    ));
    
    class MyApp extends StatefulWidget {
        @override
        _MyAppState createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
        List<String> _items;
    
        @override
        void initState() {
            super.initState();
            _items = ["item1", "item2", "item3"];
    
            new Future.delayed(const Duration(seconds: 2), () {
                setState(() {
                    _items = ["item1", "item2", "item3", "item4", "item5"];
                });
            });
        }
    
        @override
        Widget build(BuildContext context) {
            return new DefaultTabController(
                length: _items.length,
                child: new Scaffold(
                    appBar: new AppBar(
                        title: new Text("title"),
                        bottom: new TabBar(
                            tabs: _items.map((item) {
                                return new Tab(text: item);
                            }).toList(),
                        ),
                    ),
                    body: new TabBarView(
                        children: _items.map((item) {
                            return new Center(
                                child: new Text(item),
                            );
                        }).toList(),
                    ),
                ),
            );
        }
    }

    after 2s, tap item4 and item5 throw exception:

    18:29:36.747 10 800 flutter.tools I/flutter ( 7407): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
    18:29:36.786 11 800 flutter.tools I/flutter ( 7407): The following assertion was thrown while handling a gesture:
    18:29:36.786 12 800 flutter.tools I/flutter ( 7407): 'package:flutter/src/material/tab_controller.dart': Failed assertion: line 110 pos 12: 'value >= 0
    18:29:36.786 13 800 flutter.tools I/flutter ( 7407): && (value < length || length == 0)': is not true.
    18:29:36.808 14 800 flutter.tools I/flutter ( 7407): 
    18:29:36.808 15 800 flutter.tools I/flutter ( 7407): Either the assertion indicates an error in the framework itself, or we should provide substantially
    18:29:36.808 16 800 flutter.tools I/flutter ( 7407): more information in this error message to help you determine and fix the underlying cause.
    18:29:36.808 17 800 flutter.tools I/flutter ( 7407): In either case, please report this assertion by filing a bug on GitHub:
    18:29:36.808 18 800 flutter.tools I/flutter ( 7407):   https://github.com/flutter/flutter/issues/new
    18:29:36.808 19 800 flutter.tools I/flutter ( 7407): 
    18:29:36.815 20 800 flutter.tools I/flutter ( 7407): When the exception was thrown, this was the stack:
    18:29:37.011 21 800 flutter.tools I/flutter ( 7407): #2      TabController._changeIndex (package:flutter/src/material/tab_controller.dart)
    18:29:37.011 22 800 flutter.tools I/flutter ( 7407): #3      TabController.animateTo (package:flutter/src/material/tab_controller.dart:162:5)
    18:29:37.011 23 800 flutter.tools I/flutter ( 7407): #4      _TabBarState._handleTap (package:flutter/src/material/tabs.dart:864:17)
    18:29:37.011 24 800 flutter.tools I/flutter ( 7407): #5      _TabBarState.build.<anonymous closure> (package:flutter/src/material/tabs.dart:939:21)
    18:29:37.012 25 800 flutter.tools I/flutter ( 7407): #6      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:494:14)
    18:29:37.012 26 800 flutter.tools I/flutter ( 7407): #7      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:549:30)
    18:29:37.012 27 800 flutter.tools I/flutter ( 7407): #8      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
    18:29:37.012 28 800 flutter.tools I/flutter ( 7407): #9      TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:161:9)
    18:29:37.012 29 800 flutter.tools I/flutter ( 7407): #10     TapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:94:7)
    18:29:37.012 30 800 flutter.tools I/flutter ( 7407): #11     PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:315:9)
    18:29:37.012 31 800 flutter.tools I/flutter ( 7407): #12     PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:73:12)
    18:29:37.012 32 800 flutter.tools I/flutter ( 7407): #13     PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:101:11)
    18:29:37.012 33 800 flutter.tools I/flutter ( 7407): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:143:19)
    18:29:37.012 34 800 flutter.tools I/flutter ( 7407): #15     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
    18:29:37.012 35 800 flutter.tools I/flutter ( 7407): #16     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
    18:29:37.012 36 800 flutter.tools I/flutter ( 7407): #17     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
    18:29:37.012 37 800 flutter.tools I/flutter ( 7407): #18     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
    18:29:37.012 38 800 flutter.tools I/flutter ( 7407): #19     _invoke1 (dart:ui/hooks.dart:134:13)
    18:29:37.012 39 800 flutter.tools I/flutter ( 7407): #20     _dispatchPointerDataPacket (dart:ui/hooks.dart:91:5)
    18:29:37.012 40 800 flutter.tools I/flutter ( 7407): (elided 2 frames from class _AssertionError)
    18:29:37.012 41 800 flutter.tools I/flutter ( 7407): 
    18:29:37.012 42 800 flutter.tools I/flutter ( 7407): Handler: onTap
    18:29:37.012 43 800 flutter.tools I/flutter ( 7407): Recognizer:
    18:29:37.012 44 800 flutter.tools I/flutter ( 7407):   TapGestureRecognizer#24d68(debugOwner: GestureDetector, state: possible, won arena, finalPosition:
    18:29:37.012 45 800 flutter.tools I/flutter ( 7407):   Offset(286.5, 104.9), sent tap down)
    18:29:37.012 46 800 flutter.tools I/flutter ( 7407): ════════════════════════════════════════════════════════════════════════════════════════════════════
    

    flutter doctor:

    [✓] Flutter (Channel dev, v0.5.7, on Mac OS X 10.13.5 17F77, locale zh-Hans-CN)
    [✓] Android toolchain - develop for Android devices (Android SDK 27.0.3)
    [✓] iOS toolchain - develop for iOS devices (Xcode 9.4.1)
    [✓] Android Studio
        ✗ Flutter plugin not installed; this adds Flutter specific functionality.
        ✗ Dart plugin not installed; this adds Dart specific functionality.
    [✓] IntelliJ IDEA Ultimate Edition (version 2018.1)
    [✓] Connected devices (1 available)
    
    • No issues found!
    
  5. matthew5025 commented on Aug 3, 2018

    @matthew5025

    Is this related to #18481?

  6. zoechi commented on Aug 3, 2018

    @zoechi
    Contributor

    @matthew5025 are you sure this is the link you intended to post. That doesn't look related to me.

  7. matthew5025 commented on Aug 4, 2018

    @matthew5025

    @zoechi Apologies, it should have been #18481

  8. AbdulRahmanAlHamali commented on Sep 6, 2018

    @AbdulRahmanAlHamali

    Facing the same issue when adding a tab dynamically to the tab controller

  9. AbdulRahmanAlHamali commented on Sep 26, 2018

    @AbdulRahmanAlHamali

    The problem seems to be with using DefaultTabController, because it creates a TabController in its initState, and assigns it a length, which means the tab controller cannot change the length dynamically. To solve an issue similar to this, where I had to add extra tabs depending on certain conditions, I just used a custom TabController instead of the DefaultTabController

  10. flypigz commented on Jan 19, 2019

    @flypigz

    This is not only a hot reload issue, the DefaultTabController / TabController does not support dynamic changing the length.

    I meet the same issue, I need to dynamic changing the length of TabController when refreshing data from network. This is a product requirement.

    @AbdulRahmanAlHamali How do you create a custom TabController? remember we need to call the dispose() method of a TabController, otherwise it will lead to memory leak.

    I assign a ValueKey (using the length of tabs as value ) to the DefaultTabController, and it works correctly, because when the key changes, the Flutter wont reuse the current DefaultTabController.

    This is a temp fix, hope this issue to be fixed ASAP.

  11. AbdulRahmanAlHamali commented on Jan 19, 2019

    @AbdulRahmanAlHamali

    @MaxZeng I just create a TabController inside the widget and assign it to the TabBar, and every time I want to change the number of tabs in the tab controller, I dispose of the old one and create a new one with the new number of tabs.

  12. dbpprt commented on Feb 5, 2019

    @dbpprt

    Is there any progress or ETA on this issue?

  13. w4mxl commented on Mar 14, 2019

    @w4mxl

    Is this issue still being worked on?

  14. PandaGeek1024 commented on Mar 20, 2019

    @PandaGeek1024

    the cause is exactly what @AbdulRahmanAlHamali said. Any update on this, I don't see the fix in v1.2.1 yet? @zoechi

  15. github-actions commented on Aug 30, 2021

    @github-actions

    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.

  16. locked as resolved and limited conversation to collaborators on Aug 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

c: crashStack traces logged to the consoleframeworkflutter/packages/flutter repository. See also f: labels.p: material_uimaterial_ui package in flutter/packagest: hot reloadReloading code during "flutter run"

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions