在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}为什么?我已经看到了其他超级关键字不的例子,所以这就是我的困惑所在。
答案 0 :(得分:67)
TLDR:所有小部件都应该有Key key
可选参数或其构造函数。
Key
是flutter引擎在识别列表中哪个窗口小部件已更改的步骤中使用的内容。
当您拥有列表(Column
,Row
,无论如何)可能获得的相同类型的 时,此功能非常有用移除/插入。
假设你有这个(代码不起作用,但你明白了):
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是一个本地键,它采用简单值,例如字符串或整数。
如果您的小部件显示的数据比单个值复杂,那么您可以为该小部件使用ObjectKey。
保证这种类型的密钥每次都能为您提供唯一的ID。但是,如果使用它,则将其放在build
方法中。否则,您的小部件将永远不会具有相同的ID,因此元素树将永远不会找到要重用的匹配项。
GlobalKeys可用于维护应用程序中的状态,但请谨慎使用,因为它们类似于全局变量。通常更可取的是使用状态管理解决方案。
答案 2 :(得分:3)
键是用于唯一标识窗口小部件的对象。
它们用于访问或还原StatefulWidget
中的状态(如果我们的窗口小部件树都是无状态窗口小部件,则通常根本不需要它们)。
我会根据用途尝试解释各种密钥。
目的(key types
)
i.e. remove / add / reorder item to list
进行突变,其中选中的项目将被删除➡️ObjectKey, ValueKey & UniqueKey
➡️GlobalKey
➡️GlobalKey
➡️GlobalKey
➡️UniqueKey
➡️ValueKey
➡️ObjectKey
➡️GlobalObjectKey, LabeledGlobalKey whichever is appropriate, similar logic to ValueKey and ObjectKey
string/number
用作键,否则会破坏键the的目的答案 3 :(得分:0)
Key是一个可选参数,用于保留小部件树中的状态,如果要在树中移动元素的集合并保留它们的状态,则必须使用它们。
可以在此视频中找到最好的解释答案 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);
}
}