Что такое ключи в классе виджетов без сохранения состояния?
В документации по флаттеру приведен пример кода для подкласса виджетов без состояния, как показано ниже:
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}, почему? Я видел другие примеры, в которых ключевое слово super не используется, так что это мое замешательство.
5 ответов
TLDR: все виджеты должны иметь Key key
как необязательный параметр или их конструктор.Key
это то, что используется движком флаттера на этапе распознавания того, какой виджет в списке изменился.
Это полезно, когда у вас есть список (Column
, Row
(что угодно) виджетов того же типа, которые потенциально могут быть удалены / вставлены.
Допустим, у вас есть это (код не работает, но вы поняли):
new AnimatedList(
children: [
new Card(child: new Text("foo")),
new Card(child: new Text("bar")),
new Card(child: new Text("42")),
]
)
Потенциально, вы можете удалить любой из этих виджетов по отдельности одним движением.
Дело в том, что наш список как анимация при удалении ребенка. Итак, давайте удалим "бар".
new AnimatedList(
children: [
new Card(child: new Text("foo")),
new Card(child: new Text("42")),
]
)
Проблема: без Key
флаттер не сможет узнать, является ли второй элемент вашего Row
исчез. Или, если это последний, который исчез, и у второго есть дочернее изменение.
Так без Key
, потенциально вы можете иметь ошибку, из-за которой ваша анимация выхода будет воспроизводиться вместо последнего элемента!
Это где Key
происходит.
Если мы начнем снова наш пример, используя ключ, у нас будет это:
new AnimatedList(
children: [
new Card(key: new ObjectKey("foo"), child: new Text("foo")),
new Card(key: new ObjectKey("bar"), child: new Text("bar")),
new Card(key: new ObjectKey("42"), child: new Text("42")),
]
)
обратите внимание, что ключ - это не дочерний индекс, а нечто уникальное для элемента.
С этого момента, если мы удалим "бар" снова, мы будем иметь
new AnimatedList(
children: [
new Card(key: new ObjectKey("foo"), child: new Text("foo")),
new Card(key: new ObjectKey("42"), child: new Text("42")),
]
)
Благодаря key
Присутствуя, движок флаттера теперь точно знает, какой виджет был удален. И теперь наша анимация выхода будет корректно воспроизводиться на "баре" вместо "42".
Что такое ключи?
Ключи - это идентификаторы виджетов. Они есть у всех виджетов, а не только у StatelessWidgets. Они используются деревом элементов, чтобы определить, можно ли использовать виджет повторно или его нужно перестроить. Если ключ не указан (обычный случай), то для определения этого используется тип виджета.
Зачем нужны ключи?
Ключи полезны для поддержания состояния при изменении количества или положения виджетов. Если ключа нет, фреймворк Flutter может запутаться в том, какой виджет был изменен.
Когда использовать ключи?
Используйте их только тогда, когда фреймворку нужна ваша помощь, чтобы узнать, какой виджет обновлять.
В большинстве случаев вам не нужно использовать ключи. Поскольку ключи в основном полезны только для поддержания состояния, если у вас есть виджет без состояния, все дочерние элементы которого не имеют состояния, тогда нет необходимости использовать для него ключ. Ключ в этом случае не помешает, но и не поможет.
Есть некоторые микрооптимизации, которые можно сделать с помощью ключей. См. Эту статью.
Где использовать ключи?
Поместите ключ в ту часть дерева виджетов, где происходит переупорядочивание или добавление / удаление. Например, если вы переупорядочиваете элементы ListView, дочерними элементами которого являются виджеты ListTile, добавьте ключи к виджетам ListTile.
Какие ключи использовать?
Ключ - это просто идентификатор, но его можно изменить.
ValueKey
ValueKey - это локальный ключ, который принимает простое значение, например строку или целое число.
ObjectKey
Если ваш виджет отображает более сложные данные, чем одно значение, вы можете использовать ObjectKey для этого виджета.
Уникальный ключ
Этот тип ключа гарантирует каждый раз уникальный идентификатор. Если вы его используете, поместите его вbuild
метод. В противном случае у вашего виджета никогда не будет того же идентификатора, и поэтому дерево элементов никогда не найдет совпадения для повторного использования.
GlobalKey
GlobalKeys можно использовать для поддержания состояния всего приложения, но используйте их экономно, поскольку они похожи на глобальные переменные. Вместо этого часто предпочтительнее использовать решение для управления состоянием.
Примеры использования ключей
Ссылки
Ключ - это объект, который используется для уникальной идентификации виджета.
Они используются для доступа или восстановления состояния в 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
как ключ, он побеждает назначение ключей ❌
Ключ - это необязательный параметр, необходимый для сохранения состояния в вашем дереве виджетов, вы должны использовать его, если хотите переместить коллекцию элементов в вашем дереве и сохранить их состояние.
Лучшее объяснение можно найти в этом видео от Google, когда использовать ключи - Flutter Widgets 101 Ep. 4
С Dart 2.12 или новее добавить ?после ключа, чтобы сделать его необязательным, если хотите.
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);
}
}