简体   繁体   English

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

[英]What are Keys in the Stateless widgets class?

In the flutter docs there's sample code for a stateless widget subclass as shown:在 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));
  }
}

and this和这个

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

What is a key and when should this super constructor be used?什么是键,什么时候应该使用这个超级构造函数? It seems like if you have your own constructor you must have {Key key} why?看起来如果你有自己的构造函数,你必须有 {Key key} 为什么? I've seen other examples where the super keyword is not used so this is where my confusion is.我看过其他没有使用 super 关键字的例子,所以这就是我的困惑所在。

TLDR: All widgets should have a Key key as optional parameter or their constructor. TLDR:所有小部件都应该有一个Key key作为可选参数或其构造函数。 Key is something used by flutter engine at the step of recognizing which widget in a list as changed. Key是颤振引擎在识别列表中的哪个小部件已更改的步骤中使用的东西。


It is useful when you have a list ( Column , Row , whatever) of widgets of the same type that can potentially get removed/inserted.当您有一个可能被删除/插入的相同类型的小部件列表ColumnRow等)时,它很有用。

Let's say you have this (code not working, but you get the idea) :假设你有这个(代码不起作用,但你明白了):

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

Potentially, you can remove any of these widgets individually with a swipe.可能,您可以通过滑动单独删除任何这些小部件。

The thing is, our list has an animation when a child is removed.问题是,当一个孩子被移除时,我们的列表有一个动画。 So let's remove "bar".所以让我们删除“酒吧”。

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

The problem: Without Key , flutter won't be able to know if the second element of your Row disappeared.问题:如果没有Key ,flutter 将无法知道Row的第二个元素是否消失。 Or if it's the last one that disappeared and the second has its child change.或者如果它是最后一个消失而第二个有其子变化。

So without Key , you could potentially have a bug where your leave animation will be played on the last element instead!因此,如果没有Key ,您可能会遇到一个错误,即您的离开动画将在最后一个元素上播放!


This is where Key takes place.这就是Key发生的地方。

If we start our example again, using key we'd have this :如果我们再次开始我们的例子,使用 key 我们会有这个:

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

notice how the key is not the child index but something unique to the element.注意键不是子索引而是元素独有的东西。

From this point, if we remove "bar" again, we'll have从这一点来看,如果我们再次删除“bar”,我们将有

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

Thanks to key being present, flutter engine now knows for sure which widget got removed.由于存在key ,flutter 引擎现在可以确定删除了哪个小部件。 And now our leave animation will correctly play on "bar" instead of "42".现在我们的离开动画将在“bar”而不是“42”上正确播放。

What are Keys?什么是钥匙?

Keys are IDs for widgets.键是小部件的 ID。 All widgets have them, not just StatelessWidgets.所有小部件都有它们,而不仅仅是 StatelessWidgets。 They are used by the Element tree to determine if a widget can be reused or if it needs to be rebuilt.元素树使用它们来确定小部件是否可以重用或是否需要重建。 When no key is specified (the usual case), then the widget type is used to determine this.如果未指定键(通常情况),则使用小部件类型来确定这一点。

Why use Keys?为什么要使用密钥?

Keys are useful for maintaining state when the number or position of widgets changes.当小部件的数量或位置发生变化时,键对于维持状态很有用。 If there is no key then the Flutter framework can get confused about which widget changed.如果没有键,那么 Flutter 框架可能会对更改的小部件感到困惑。

When to use Keys?什么时候使用密钥?

Only use them when the framework needs your help to know which widget to update.仅在框架需要您的帮助以了解要更新哪个小部件时才使用它们。

Most of the time you don't need to use keys.大多数时候您不需要使用密钥。 Since keys are mostly only useful for maintaining state, if you have a stateless widget whose children are all stateless, then there is no need to use a key on it.由于键主要仅用于维护状态,如果您有一个无状态小部件,其子部件都是无状态的,则无需在其上使用键。 It won't hurt to use a key in this case, but it also won't help.在这种情况下使用密钥不会有什么坏处,但它也无济于事。

There are some micro-optimizations you can make using keys.您可以使用密钥进行一些微优化。 See this article .请参阅这篇文章

Where to use Keys?在哪里使用密钥?

Put the key at the part of the widget tree where the reordering or addition/deletion is taking place.将密钥放在正在发生重新排序或添加/删除的小部件树的部分。 For example, if you are reordering the items of a ListView whose children are ListTile widgets, then add the keys to the ListTile widgets.例如,如果您要对子项是 ListTile 小部件的 ListView 的项目重新排序,则将键添加到 ListTile 小部件。

What kind of Keys to use?使用什么样的密钥?

A key is just an id, but the kind of ID you can can vary.密钥只是一个 ID,但您可以更改 ID 的类型。

ValueKey值键

A ValueKey is a local key that takes a simple value like a string or integer. ValueKey 是一个本地键,它采用一个简单的值,如字符串或整数。

ObjectKey对象键

If you widget is displaying more complex data than a single value, then you can use an ObjectKey for that widget.如果您的小部件显示比单个值更复杂的数据,那么您可以为该小部件使用 ObjectKey。

UniqueKey唯一键

This type of key is guaranteed to give you a unique ID every time.这种类型的密钥保证每次都会为您提供唯一的 ID。 If you use it, though, do NOT put it in the build method.但是,如果您使用它,请不要将它放在build方法中。 Otherwise your widget will never have the same ID and so the Element tree will never find a match to reuse.否则,您的小部件将永远不会具有相同的 ID,因此元素树将永远找不到要重用的匹配项。

GlobalKey全局键

GlobalKeys can be used to maintain state across your app, but use them sparingly because they are similar to global variables. GlobalKeys 可用于维护整个应用程序的状态,但请谨慎使用它们,因为它们类似于全局变量。 It is often preferable to use a state management solution instead.通常最好使用状态管理解决方案。

Examples of using Keys使用密钥的示例

References参考

Key is object that is used to identify a widget uniquely.键是用于唯一标识小部件的对象。

They are used to access or restore state In a StatefulWidget (Mostly we don't need them at all if our widget tree is all Stateless Widgets).它们用于访问或恢复StatefulWidget (如果我们的小部件树都是无状态小部件,则大多数情况下我们根本不需要它们)。 There are various types of key that I will try to explain on the basis of usage.我将尝试根据用法解释各种类型的密钥。

Purpose ( key types )目的( key types

1. Mutate the collection ie remove / add / reorder item to list in stateful widget like draggable todo list where checked items get removed 1. 改变集合, ie remove / add / reorder item to list在有状态小部件中列出,例如可拖动的待办事项列表,其中选中的项目被删除

➡️ ObjectKey, ValueKey & UniqueKey ➡️ ObjectKey, ValueKey & UniqueKey

2. Move widget from one Parent to another preserving it's state. 2. 将小部件从一个父级移动到另一个保持其状态。

➡️ GlobalKey ➡️ GlobalKey

3. Display same Widget in multiple screens and holding its state. 3. 在多个屏幕中显示相同的 Widget 并保持其状态。

➡️ GlobalKey ➡️ GlobalKey

4. Validate Form. 4. 验证表单。

➡️ GlobalKey ➡️ GlobalKey

5. You want to give a key without using any data. 5. 您想在不使用任何数据的情况下提供密钥。

➡️ UniqueKey ➡️ UniqueKey

6. If you can use a certain fields of data like UUID of users as unique Key. 6.如果你可以使用用户的UUID等数据的某些字段作为唯一的Key。

➡️ ValueKey ➡️ 值ValueKey

7. If you do not have any unique field to use as key but object itself is unique. 7. 如果您没有任何唯一字段用作键,但对象本身是唯一的。

➡️ ObjectKey ➡️ ObjectKey

8. If you have multiple Forms or Multiple Widgets of the same type that need GlobalKey. 8. 如果您有多个需要 GlobalKey 的相同类型的 Forms 或 Multiple Widgets。

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

❌ Do not use random string/number as key, it defeats the purpose of keys ❌ ❌不要使用随机string/number作为密钥,这违背了密钥的目的❌

The Key is an optional parameter needed to preserve state in your widget tree, you have to use them if you want to move a collection of elements in your tree and preserve the state of them. Key 是在小部件树中保留状态所需的可选参数,如果要移动树中的元素集合并保留它们的状态,则必须使用它们。

The best explanation can be found in this video by Google When to Use Keys - Flutter Widgets 101 Ep.最好的解释可以在 Google何时使用密钥的视频中找到- Flutter Widgets 101 Ep。 4 4

With Dart 2.12 or later, add ?对于 Dart 2.12 或更高版本,添加? after Key to make it optional if you want.如果需要,在 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);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM