无状态小部件类中的键是什么?

Dan*_*T29 56 dart flutter

在flutter docs中,有一个无状态小部件子类的示例代码,如下所示:

class GreenFrog extends StatelessWidget {
  const GreenFrog({ Key key }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return new Container(color: const Color(0xFF2DBD3A));
  }
}
Run Code Online (Sandbox Code Playgroud)

还有这个

class Frog extends StatelessWidget {
  const Frog({
    Key key,
    this.color: const Color(0xFF2DBD3A),
    this.child,
  }) : super(key: key);

  final Color color;

  final Widget child;

  @override
  Widget build(BuildContext context) {
    return new Container(color: color, child: child);
  }
}
Run Code Online (Sandbox Code Playgroud)

什么是关键,什么时候应该使用这个超级构造函数?好像你有自己的构造函数,你必须有{Key key}为什么?我已经看到了其他没有使用super关键字的例子,所以这就是我的困惑所在.

Rém*_*let 79

TLDR:所有的部件应该有一个Key key作为可选的参数或者其构造. Key是在识别列表中哪个窗口小部件已更改的步骤中由颤振引擎使用的内容.


当您拥有可能被删除/插入的相同类型的小部件列表(Column,Row无论如何)时,它非常有用.

假设你有这个(代码不起作用,但你明白了):

AnimatedList(
  children: [
    Card(child: Text("foo")),
    Card(child: Text("bar")),
    Card(child: Text("42")),
  ]
)
Run Code Online (Sandbox Code Playgroud)

您可以使用滑动单独删除任何这些小部件.

问题是,当一个孩子被移除时,我们的列表有一个动画.所以我们删除"bar".

AnimatedList(
  children: [
    Card(child: Text("foo")),
    Card(child: Text("42")),
  ]
)
Run Code Online (Sandbox Code Playgroud)

问题:没有Key,颤动就无法知道你的第二个元素是否Row消失了.或者,如果它是最后一个消失,第二个有它的孩子改变.

所以没有Key,你可能会有一个错误,你的离开动画将在最后一个元素上播放!


这是Key发生的地方.

如果我们再次开始我们的例子,使用密钥,我们有这个:

AnimatedList(
  children: [
    Card(key: ObjectKey("foo"), child: Text("foo")),
    Card(key: ObjectKey("bar"), child: Text("bar")),
    Card(key: ObjectKey("42"), child: Text("42")),
  ]
)
Run Code Online (Sandbox Code Playgroud)

注意键不是子索引,而是元素的独特之处.

从这一点来说,如果我们再次删除"bar",我们就会拥有

AnimatedList(
  children: [
    Card(key: ObjectKey("foo"), child: Text("foo")),
    Card(key: ObjectKey("42"), child: Text("42")),
  ]
)
Run Code Online (Sandbox Code Playgroud)

由于key存在,颤振引擎现在知道哪个小部件被删除.现在,我们的离开动画将正确播放"bar"而不是"42".

  • @IshanFernando没有.但是当没有键时,颤动使用窗口小部件类型,它在数组中的位置作为参考. (7认同)
  • flutter添加默认密钥吗? (4认同)
  • 我开始明白你在说什么,我也是移动开发的新手,对我来说也是如此。只是为了从您的解释中澄清,现在有办法区分卡片元素,即使它们作为子元素具有不同的文本?因此,为了解决这个问题,使用键作为每个元素的唯一 ID。它是否正确? (3认同)
  • 确切地。为了区分小部件,默认情况下,混乱会使用它们在列表中的类型和索引,除非您指定键。 (3认同)

Sur*_*gch 27

什么是钥匙?

键是小部件的 ID。所有小部件都有它们,而不仅仅是 StatelessWidgets。元素树使用它们来确定小部件是否可以重用或是否需要重建。如果未指定键(通常情况),则使用小部件类型来确定这一点。

为什么要使用密钥?

当小部件的数量或位置发生变化时,键对于维持状态很有用。如果没有键,那么 Flutter 框架可能会对更改的小部件感到困惑。

什么时候使用密钥?

仅在框架需要您的帮助以了解要更新哪个小部件时才使用它们。

大多数时候您不需要使用密钥。由于键主要仅用于维护状态,如果您有一个无状态小部件,其子部件都是无状态的,则无需在其上使用键。在这种情况下使用密钥不会有什么坏处,但它也无济于事。

您可以使用密钥进行一些微优化。请参阅这篇文章

在哪里使用密钥?

将密钥放在正在发生重新排序或添加/删除的小部件树的部分。例如,如果您要对子项是 ListTile 小部件的 ListView 的项目重新排序,则将键添加到 ListTile 小部件。

使用什么样的密钥?

密钥只是一个 ID,但您可以更改 ID 的类型。

值键

ValueKey 是一个本地键,它采用一个简单的值,如字符串或整数。

对象键

如果您的小部件显示比单个值更复杂的数据,那么您可以为该小部件使用 ObjectKey。

唯一键

这种类型的密钥保证每次都会为您提供唯一的 ID。但是,如果您使用它,请不要将其放入build方法中。否则,您的小部件将永远不会具有相同的 ID,因此元素树将永远找不到要重用的匹配项。

全局键

GlobalKeys 可用于维护整个应用程序的状态,但请谨慎使用它们,因为它们类似于全局变量。通常最好使用状态管理解决方案。

使用密钥的示例

参考


erl*_*man 8

键是用于唯一标识小部件的对象。

它们用于访问或恢复状态StatefulWidget(如果我们的小部件树都是无状态小部件,则大多数情况下我们根本不需要它们)。我将尝试根据用法解释各种类型的密钥。

目的 ( key types)

1. 改变i.e. remove / add / reorder item to list有状态小部件中的集合,例如可拖动的待办事项列表,其中选中的项目被删除

?? ObjectKey, ValueKey & UniqueKey

2. 将小部件从一个父级移动到另一个保持其状态。

?? GlobalKey

3. 在多个屏幕中显示相同的 Widget 并保持其状态。

?? GlobalKey

4. 验证表单。

?? GlobalKey

5. 您想在不使用任何数据的情况下提供密钥。

?? UniqueKey

6.如果你可以使用用户的UUID等数据的某些字段作为唯一的Key。

?? ValueKey

7. 如果您没有任何唯一字段用作键,但对象本身是唯一的。

?? ObjectKey

8. 如果您有多个需要 GlobalKey 的相同类型的 Forms 或 Multiple Widgets。

?? GlobalObjectKey, LabeledGlobalKey whichever is appropriate, similar logic to ValueKey and ObjectKey

? 不要使用随机string/number作为密钥,它违背了密钥的目的?