New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error using more than 2 tabs with TabController and AutomaticKeepAliveClientMixin #18350

Closed
hillelcoren opened this Issue Jun 11, 2018 · 2 comments

Comments

Projects
None yet
2 participants
@hillelcoren

hillelcoren commented Jun 11, 2018

Steps to Reproduce

Here's a sample app which demonstrates the problem, you can trigger the error by switching between the tabs. For example selecting the 3rd tab and then the 1st tab.

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget {

  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {

  TabController _controller;

  @override
  void initState() {
    super.initState();
    _controller = new TabController(vsync: this, length:3);
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Sample App'),
          bottom: TabBar(
            controller: _controller,
            isScrollable: true,
            tabs: [
              Tab(
                text: 'Page 1',
              ),
              Tab(
                text: 'Page 2',
              ),
              Tab(
                text: 'Page 3',
              ),
            ],
          ),
        ),
        body: TabBarView(
          controller: _controller,
          children: <Widget>[
            Page1(),
            Page2(),
            Page3(),
          ],
        ),
      ),
    );
  }
}

class Page1 extends StatefulWidget {

  static final GlobalKey<FormFieldState<String>> value1Key = GlobalKey<FormFieldState<String>>();

  @override
  _Page1State createState() => new _Page1State();
}

class _Page1State extends State<Page1> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      key: Page1.value1Key,
    );
  }
}

class Page2 extends StatefulWidget {

  static final GlobalKey<FormFieldState<String>> value2Key = GlobalKey<FormFieldState<String>>();

  @override
  _Page2State createState() => new _Page2State();
}

class _Page2State extends State<Page2> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      key: Page2.value2Key,
    );
  }
}

class Page3 extends StatefulWidget {

  static final GlobalKey<FormFieldState<String>> value3Key = GlobalKey<FormFieldState<String>>();

  @override
  _Page3State createState() => new _Page3State();
}

class _Page3State extends State<Page3> with AutomaticKeepAliveClientMixin {
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      key: Page3.value3Key,
    );
  }
}

Logs

I/flutter ( 4547): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 4547): The following assertion was thrown while finalizing the widget tree:
I/flutter ( 4547): Duplicate GlobalKey detected in widget tree.
I/flutter ( 4547): The following GlobalKey was specified multiple times in the widget tree. This will lead to parts of
I/flutter ( 4547): the widget tree being truncated unexpectedly, because the second time a key is seen, the previous
I/flutter ( 4547): instance is moved to the new location. The key was:
I/flutter ( 4547): - [LabeledGlobalKey<FormFieldState<String>>#742f4]
I/flutter ( 4547): This was determined by noticing that after the widget with the above global key was moved out of its
I/flutter ( 4547): respective previous parents, those previous parents never updated during this frame, meaning that
I/flutter ( 4547): they either did not update at all or updated before the widget was moved, in either case implying
I/flutter ( 4547): that they still think that they should have a child with that global key.
I/flutter ( 4547): The specific parents that did not update after having one or more children forcibly removed due to
I/flutter ( 4547): GlobalKey reparenting are:
I/flutter ( 4547): - Padding(padding: EdgeInsets(12.0, 0.0, 12.0, 0.0), renderObject: RenderPadding#86551 NEEDS-LAYOUT
I/flutter ( 4547):   DETACHED)
I/flutter ( 4547):   Page1(state: _Page1State#aa8d1)
I/flutter ( 4547):   Padding(padding: EdgeInsets(12.0, 0.0, 12.0, 0.0), renderObject: RenderPadding#0adeb NEEDS-LAYOUT
I/flutter ( 4547):   DETACHED)
I/flutter ( 4547): A GlobalKey can only be specified on one widget at a time in the widget tree.
I/flutter ( 4547): 
I/flutter ( 4547): When the exception was thrown, this was the stack:
I/flutter ( 4547): #0      BuildOwner.finalizeTree.<anonymous closure> (package:flutter/src/widgets/framework.dart:2386:15)
I/flutter ( 4547): #1      BuildOwner.finalizeTree (package:flutter/src/widgets/framework.dart:2407:8)
I/flutter ( 4547): #2      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:628:18)
I/flutter ( 4547): #3      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:208:5)
I/flutter ( 4547): #4      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter ( 4547): #5      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter ( 4547): #6      _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter ( 4547): #7      _invoke (dart:ui/hooks.dart:120:13)
I/flutter ( 4547): #8      _drawFrame (dart:ui/hooks.dart:109:3)
I/flutter ( 4547): ════════════════════════════════════════════════════════════════════════════════════════════════════
[√] Flutter (Channel dev, v0.5.1, on Microsoft Windows [Version 10.0.16299.431], locale en-US)
    • Flutter version 0.5.1 at C:\Users\hillel\Documents\flutter
    • Framework revision c7ea3ca377 (13 days ago), 2018-05-29 21:07:33 +0200
    • Engine revision 1ed25ca7b7
    • Dart version 2.0.0-dev.58.0.flutter-f981f09760

[√] Android toolchain - develop for Android devices (Android SDK 27.0.3)
    • Android SDK at C:\Users\hillel\AppData\Local\Android\sdk
    • Android NDK location not configured (optional; useful for native profiling support)
    • Platform android-27, build-tools 27.0.3
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b02)
    • All Android licenses accepted.

[√] Android Studio (version 3.1)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 24.2.1
    • Dart plugin version 173.4700
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b02)

[√] Connected devices (1 available)
    • Android SDK built for x86 64 • emulator-5554 • android-x64 • Android P (API 27) (emulator)

• No issues found!

Thanks for your help! Hope it's actually a bug and not user error...

@zoechi

This comment has been minimized.

Contributor

zoechi commented Jun 11, 2018

@hillelcoren

This comment has been minimized.

hillelcoren commented Jul 3, 2018

This can probably be marked as a duplicate of #11895

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment