首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在小部件树中检测到重复GlobalKey

在小部件树中检测到重复GlobalKey
EN

Stack Overflow用户
提问于 2018-03-19 19:47:46
回答 15查看 97K关注 0票数 75

在从globalKey导航到Screen B并单击"Cancel“按钮返回Screen A后,我会遇到一个Screen B错误。

问题似乎是,Screen B要么

  • A)未得到正确处置
  • ( B)没有做它本来可以做的事情

我也不知道

  • 如果我只是删除globalKey的使用,会发生什么不好的事情呢?(为了更好地了解基本面)
  • 我怎样才能正确地解决这个问题?

StatefulWidget文档状态:在这里输入链接描述

如果StatefulWidget的创建者使用GlobalKey作为密钥,则当它从树中的一个位置移动到另一个位置时,它会保留相同的状态对象。因为带GlobalKey的小部件最多只能在树中的一个位置使用,所以使用GlobalKey的小部件最多有一个关联元素。框架在将带全局键的小部件从树中的一个位置移动到另一个位置时利用此属性,将与该小部件关联的(唯一)子树从旧位置嫁接到新位置(而不是在新位置重新创建子树)。与StatefulWidget关联的状态对象与子树的其余部分一起嫁接,这意味着状态对象在新位置被重用(而不是重新创建)。然而,为了符合嫁接的条件,必须将小部件插入到从旧位置移除它的动画框架中的新位置。

控制台错误输出:

代码语言:javascript
复制
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown while finalizing the widget tree:
Duplicate GlobalKey detected in widget tree.
The following GlobalKey was specified multiple times in the widget tree. This will lead to parts of
the widget tree being truncated unexpectedly, because the second time a key is seen, the previous
instance is moved to the new location. The key was:
- [LabeledGlobalKey<FormFieldState<String>>#3c76d]
This was determined by noticing that after the widget with the above global key was moved out of its
previous parent, that previous parent never updated during this frame, meaning that it either did
not update at all or updated before the widget was moved, in either case implying that it still
thinks that it should have a child with that global key.
The specific parent that did not update after having one or more children forcibly removed due to
GlobalKey reparenting is:
- Column(direction: vertical, mainAxisAlignment: start, crossAxisAlignment: center, renderObject:
RenderFlex#7595c relayoutBoundary=up1 NEEDS-PAINT)
A GlobalKey can only be specified on one widget at a time in the widget tree.

因此,错误输出的这一部分:

在此框架期间,以前的父级从未更新过,这意味着它要么根本没有更新,要么在移动小部件之前更新。

这让我觉得我的旧的“重要小部件”有机会做一些事情(要么重新定位自己,要么发布一些可以正确处理的东西。

这似乎在framework.dart on assert(_children.contains(child))中失败了。

代码语言:javascript
复制
  @override
  void forgetChild(Element child) {
    assert(_children.contains(child));
    assert(!_forgottenChildren.contains(child));
    _forgottenChildren.add(child);
  }
EN

回答 15

Stack Overflow用户

发布于 2018-09-23 03:32:02

在我的例子中,它就像一个热的重装错误。只需重新启动调试工作为我。

票数 128
EN

Stack Overflow用户

发布于 2019-10-23 06:50:30

从键变量中移除静态类型和最终类型,这样如果

代码语言:javascript
复制
static final GlobalKey<FormState> _abcKey = GlobalKey<FormState>();

将其更改为

代码语言:javascript
复制
GlobalKey<FormState> _abcKey = GlobalKey<FormState>();
票数 44
EN

Stack Overflow用户

发布于 2018-03-19 20:56:44

多亏了冈特的赞扬,我才确定这是因为屏幕没有得到妥善的处理。

Flutter的pushReplacement调用Route.dispose,这将最终释放屏幕。

我仍然不确定这是否会起作用:

小部件必须插入到同一动画帧中的新位置。

我不知道这种诡计会给什么情况带来好处。但是,我的问题解决了。我只需要打个电话给我换个电话。

以下是可用的选项:

  • 使用pushAB,从B只使用Navigator.pop
  • 使用pushReplacementAB,从BA

我最近开始使用弗鲁罗进行路由,还有几种处理这些情况的方法(注意可选参数替换):

  • 使用router.navigateTo(context, route, replace: false)AB,使用Navigator.popB
  • 使用router.navigateTo(context, route, replace: true) (从AB )和从BA (键是replace: true)
票数 21
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49371221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档