【问题标题】:Multiple widgets used the same GlobalKey多个小部件使用相同的 GlobalKey
【发布时间】:2018-09-26 12:05:25
【问题描述】:

我正在使用 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 次后会出现错误。 感谢您的任何帮助。

【问题讨论】:

  • 这很可能是TabBarView 的一个错误,其中新旧子代重叠一帧。请填写问题。
  • @RémiRousselet 谢谢,我做了,还没有...

标签: dart flutter


【解决方案1】:

您能否“手动”创建密钥并使用静态/常量值?例如...

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__');
}

然后在...

    body: new TabBarView(
            children: [
              new RefreshIndicator(new RefreshIndicator(
// Use the Manual Static Value instead ...
                key: RIKeys.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);
                    }),
              ),

我已经在类似的情况下取得了一些成功...尤其是使用 redux 或其他类似模式...

【讨论】:

  • 在表单小部件验证的情况下,我们如何像 riKey1.currentState.validate() 一样访问。
【解决方案2】:

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

只需将GlobalKey 更改为GlobalObjectKey

如下所示。

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

【讨论】:

    【解决方案3】:

    对于需要继续使用 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,
          ),
          ...
        ),
    ]
    

    【讨论】:

    • type 'LabeledGlobalKey>' 不是类型 'GlobalKey' 的子类型
    • 我不完全了解您的情况,但请尝试: static final josKeys1 = GlobalKey();
    【解决方案4】:

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

    用这种方法解决问题

      @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

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

    Container(
            refKey: …,
    )
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        由于循环依赖,我在颤振项目中遇到了这个问题。 请检查Widget A是否导入Widget BWidget B是否导入Windget A

        【讨论】:

          【解决方案7】:

          和上面的@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;
          

          【讨论】:

          • 我在做GlobalKey _globalKey = JosKeys.josKeys1; 时收到type 'ValueKey&lt;String&gt;' is not a subtype of type 'GlobalKey&lt;State&lt;StatefulWidget&gt;&gt;' 有什么想法吗?
          • 这会抛出一个错误。
          猜你喜欢
          • 2019-06-07
          • 2020-10-01
          • 1970-01-01
          • 2021-08-26
          • 2023-03-04
          • 2019-06-01
          • 2020-10-21
          • 2021-07-01
          • 2019-05-27
          相关资源
          最近更新 更多