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

时间:2018-04-28 20:40:06

标签: dart flutter

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

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

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

和这个

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

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

5 个答案:

答案 0 :(得分:67)

TLDR:所有小部件都应该有Key key 可选参数或其构造函数。 Key是flutter引擎在识别列表中哪个窗口小部件已更改的步骤中使用的内容。

当您拥有列表ColumnRow,无论如何)可能获得的相同类型 时,此功能非常有用移除/插入。

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

AnimatedList(
  children: [
    Card(child: Text("foo")),
    Card(child: Text("bar")),
    Card(child: Text("42")),
  ]
)

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

问题是,当孩子被移除时,我们的列表会有动画。所以让我们删除“bar”。

AnimatedList(
  children: [
    Card(child: Text("foo")),
    Card(child: Text("42")),
  ]
)

问题:如果没有Key,flutter将无法知道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")),
  ]
)

注意密钥不是子索引,但该元素是唯一的。

从这一点来说,如果我们再次删除“bar”,我们就会

AnimatedList(
  children: [
    Card(key: ObjectKey("foo"), child: Text("foo")),
    Card(key: ObjectKey("42"), child: Text("42")),
  ]
)

感谢key存在,flutter引擎现在知道哪个小部件被删除了。现在我们的离开动画将正确播放“bar”而不是“42”。

答案 1 :(得分:9)

什么是键?

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

为什么要使用按键?

当小部件的数量或位置更改时,键对于保持状态很有用。如果没有密钥,则Flutter框架可能会混淆哪个控件已更改。

何时使用按键?

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

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

您可以使用键进行一些微优化。参见this article

在哪里使用密钥?

将键放在小部件树中进行重新排序或添加/删除的部分。例如,如果要重新排序其子项为ListTile小部件的ListView的项目,则将键添加到ListTile小部件。

要使用哪种密钥?

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

ValueKey

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

ObjectKey

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

UniqueKey

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

GlobalKey

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

使用键的示例

参考

答案 2 :(得分:3)

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

它们用于访问或还原StatefulWidget中的状态(如果我们的窗口小部件树都是无状态窗口小部件,则通常根本不需要它们)。 我会根据用途尝试解释各种密钥。

目的(key types

1。在有状态窗口小部件(例如可拖动的待办事项列表)中对集合 i.e. remove / add / reorder item to list 进行突变,其中选中的项目将被删除

➡️ObjectKey, ValueKey & UniqueKey

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

➡️GlobalKey

3。在多个屏幕中显示相同的小部件并保持其状态。

➡️GlobalKey

4。验证表单。

➡️GlobalKey

5。您想提供一个不使用任何数据的密钥。

➡️UniqueKey

6。如果您可以将某些数据字段(例如用户的UUID)用作唯一密钥。

➡️ValueKey

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

➡️ObjectKey

8。如果您有多个需要GlobalKey的表单或相同类型的多个小部件。

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

❌请勿将随机string/number用作键,否则会破坏键the的目的

答案 3 :(得分:0)

Key是一个可选参数,用于保留小部件树中的状态,如果要在树中移动元素的集合并保留它们的状态,则必须使用它们。

由Google When to Use Keys - Flutter Widgets 101 Ep. 4

可以在此视频中找到最好的解释

答案 4 :(得分:0)

对于 Dart 2.12 或更高版本,如果需要,请在 Key 后添加 ? 以使其成为可选。

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