多个小部件使用相同的GlobalKey

时间:2018-04-16 16:56:08

标签: dart flutter

我正在使用Flutter。我有一个简单的应用程序,有3个标签。每个选项卡中都有一个带有ListView的RefreshIndicator。行以另一种方法构建。 这是代码:

 @override
 Widget build(BuildContext context) {
    final GlobalKey<RefreshIndicatorState> _RIKey1 = new GlobalKey<RefreshIndicatorState>();
    final GlobalKey<RefreshIndicatorState> _RIKey2 = new GlobalKey<RefreshIndicatorState>();
    final GlobalKey<RefreshIndicatorState> _RIKey3 = new GlobalKey<RefreshIndicatorState>();

    debugPrint(_RIKey1.toString());
    debugPrint(_RIKey2.toString());
    debugPrint(_RIKey3.toString());
    return new Scaffold(
      body: new DefaultTabController(
        length: 3,
        child: new Scaffold(
          appBar: new AppBar(
            bottom: new TabBar(
              tabs: [
                new Tab(icon: new Icon(Icons.view_list)),
                new Tab(icon: new Icon(Icons.hotel)),
                new Tab(icon: new Icon(Icons.assessment)),
              ],
            ),
            title: new Text('Data'),
          ),
          body: new TabBarView(
            children: [
              new RefreshIndicator(
                key: _RIKey1,
                onRefresh: _actualizoData,
                child: new ListView.builder(
                    padding: new EdgeInsets.only(top: 5.0),
                    itemCount: linea_reservas.length * 2,
                    itemBuilder: (BuildContext context, int position) {
                      if (position.isOdd) return new Divider();
                      final index = position ~/ 2;
                      return _buildRow(index);
                    }),
              ),
              new RefreshIndicator(
                key: _RIKey2,
                onRefresh: _actualizoData,
                child: new ListView.builder(
                    padding: new EdgeInsets.only(top: 8.0),
                    itemCount: linea_inouthouse.length * 2,
                    itemBuilder: (BuildContext context, int position) {
                      if (position.isOdd) return new Divider();
                      final index = position ~/ 2;
                      return _buildRowInOutHouse(index);
                    }),
              ),
              new RefreshIndicator(
                key: _RIKey3,
                onRefresh: _actualizoData,
                child: new ListView.builder(
                    padding: new EdgeInsets.only(top: 5.0),
                    itemCount: linea_ocupacion.length * 2,
                    itemBuilder: (BuildContext context, int position) {
                      if (position.isOdd) return new Divider();
                      final index = position ~/ 2;
                      return _buildRowOcupacion(index);
                    }),
              ),
            ],
          ),
        ),
      ),
    );
  }

我添加了debugPrints,输出是6行,而不是3.

I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#4d76c]
I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#59b9e]
I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#2c88b]
I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#7bd42]
I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#1c984]
I/flutter ( 5252): [LabeledGlobalKey<RefreshIndicatorState>#dbe20]

该应用有效,但在更改标签几次后,它会因此错误而崩溃:

    I/flutter ( 5252): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 5252): The following assertion was thrown building NotificationListener<KeepAliveNotification>:
I/flutter ( 5252): Multiple widgets used the same GlobalKey.
I/flutter ( 5252): The key [LabeledGlobalKey<RefreshIndicatorState>#7bd42] was used by multiple widgets. The parents of
I/flutter ( 5252): those widgets were:
I/flutter ( 5252): - RepaintBoundary-[<[LabeledGlobalKey<RefreshIndicatorState>#7bd42]>](renderObject:
I/flutter ( 5252):   RenderRepaintBoundary#60a4a DETACHED)
I/flutter ( 5252): - RepaintBoundary-[<[LabeledGlobalKey<RefreshIndicatorState>#7bd42]>](renderObject:
I/flutter ( 5252):   RenderRepaintBoundary#c8cdb NEEDS-LAYOUT NEEDS-PAINT)
I/flutter ( 5252): A GlobalKey can only be specified on one widget at a time in the widget tree.

密钥是在Build方法中生成的,所以,我不明白为什么Multiple widgets used the same GlobalKey错误

为什么再次生成密钥,为什么它不是唯一的?我不是说一千个意图,在标签之间更换4到5次后出现错误。 感谢您的任何帮助。

6 个答案:

答案 0 :(得分:1)

你可以手工制作钥匙吗?#34;并使用静态/常量值?例如...

    ColA   ColB   ColC
    Onion  Ounces  12
    Onion  Ounces  6
    Carrot Kilo    3
    Basil  Grams   25
    Carrot Kilo    6
    Basil  Cups    3
    __________________
    Onion  Ounces  18
    Carrot Kilo    9
    Basil  Grams   25
    Basil  Cups    3

然后在......

import 'package:flutter/widgets.dart';

class RIKeys {
  static final riKey1 = const Key('__RIKEY1__');
  static final riKey2 = const Key('__RIKEY2__');
  static final riKey3 = const Key('__RIKEY3__');
}

我在类似情况下做到了这一点并取得了一些成功......特别是对于redux或其他类似的模式......

答案 1 :(得分:1)

对于那些需要继续使用GlobalKey的人:

import 'package:flutter/widgets.dart';

class JosKeys {
  static final josKeys1 = GlobalKey();
  static final josKeys2 = GlobalKey();
}

使用如下:

[
    CoachTutorialModel(
      ids: "post",
      globalKeys: JosKeys.josKeys1,
      icons: Icon(
        Icons.message,
        color: Colors.white,
        size: 90,
      ),
      ...
    ),

   CoachTutorialModel(
      ids: "post2",
      globalKeys: JosKeys.josKeys2,
      icons: Icon(
        Icons.message,
        color: Colors.white,
        size: 90,
      ),
      ...
    ),
]

答案 2 :(得分:0)

与上面的@babernethy一样,您可以拥有

import 'package:flutter/widgets.dart';

class JosKeys {
  static final josKeys1 = const Key('__JosKey1__');
  static final josKeys2 = const Key('__JosKey2__');
}

然后在您的一个全局密钥上执行此操作,请确保每个全局密钥具有不同的JosKeys.josKeys{number}

GlobalKey _globalKey = JosKeys.josKeys1;

答案 3 :(得分:0)

我们可以通过其定义和要求以不同的方式解决此问题:

只需使用这种方式即可解决问题

  @override
  Widget build(BuildContext context) {
      //... return
      new RefreshIndicator(key: new GlobalKey<RefreshIndicatorState>(),  ...
  }

使用自定义debugLabel

将密钥从static final更改为final,然后添加debugLabel解决了

class _LoginFormState extends State<yourStatefulWidget> {
  final GlobalKey<FormState> _formKey =
      new GlobalKey<FormState>(debugLabel: '_LoginFormState');
  ...

使用final

创建密钥

static更改为非静态是指每次小部件都在重新创建密钥,因此它不再是全局的。这违背了它的目的。

final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

key更改为refKey

假设您使用包装了Container小部件的自定义小部件。需要将键从自定义小部件传递到容器,并在包装​​构造函数中使用参数key。遇到同样的问题。修复以避免在包装构造函数中使用单词key,将其更改为refKey

Container(
        refKey: …,
)

答案 4 :(得分:0)

这段代码对我有用......我想创建一个表单键列表......

只是用 GlobalKey 改变 GlobalObjectKey

如下所示。

final List<GlobalObjectKey<FormState>> formKeyList = List.generate(10, (index) => GlobalObjectKey<FormState>(index));

答案 5 :(得分:0)

在我的例子中,我在一个在多个地方调用的方法中添加了一个小部件的键,代码不是我的,所以需要一段时间来调试,把它留在这里也许对某人有帮助。