Ответ
Ключи (Key) в Flutter используются для идентификации виджетов при перестроении дерева. Разница между LocalKey и GlobalKey — в их области видимости и возможностях.
| Аспект | LocalKey | GlobalKey |
|---|---|---|
| Область видимости | В пределах родительского виджета (Element). |
Глобально во всем приложении. |
| Основная цель | Идентификация виджетов-братьев при реконфигурации списка или анимированных переходах. | Получение доступа к состоянию (State) или контексту (BuildContext) виджета из любой точки приложения. |
| Производительность | Легковесные. | Дорогие, так как требуют глобальной регистрации и могут мешать сборке мусора. |
| Типы | ValueKey, ObjectKey, UniqueKey. |
GlobalKey (обычный) и GlobalKey<FormState>, GlobalKey<ScaffoldState> и т.д. |
Пример LocalKey (ValueKey в ListView):
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return ListTile(
// ValueKey помогает Flutter корректно анимировать
// перемещение/удаление элементов при изменении списка.
key: ValueKey(item.id),
title: Text(item.title),
);
},
)
Пример GlobalKey (для доступа к состоянию Form):
class MyForm extends StatelessWidget {
// Создаем глобальный ключ для формы
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey, // Передаем ключ форме
child: Column(
children: [
TextFormField(validator: (value) { /* ... */ }),
ElevatedButton(
onPressed: () {
// Используем ключ для валидации и сохранения формы
// извне самого виджета Form.
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// Отправка данных...
}
},
child: Text('Отправить'),
),
],
),
);
}
}
Правило: Всегда используйте LocalKey, если достаточно его возможностей. Применяйте GlobalKey только в случаях, когда необходим глобальный доступ к состоянию виджета, например, для управления Form, Scaffold (через ScaffoldMessenger) или анимации виджетов между разными ветками дерева.
Ответ 18+ 🔞
Э, слушай, про ключи в Flutter. Ну это ж классика, ебать мои старые костыли. Сидишь такой, пишешь код, а потом бац — виджеты хуёво анимируются или состояние не достать. А всё потому, что про ключи нихуя не понял.
Короче, есть два главных типа: LocalKey и GlobalKey. Разница проще некуда, если не тупить.
LocalKey — это как твой пропуск в родном офисе. Действует только в пределах одного этажа (родительского виджета). Нужен, чтобы Flutter не охуел, когда ты в списке элементы местами меняешь или анимацию делаешь. Без ключа он может перепутать, какой виджет куда, и всё начнёт дико глючить и пересоздаваться. А с ключом — всё чётко, братья-виджеты друг друга узнают. Легковесный, дешёвый. Типы у него: ValueKey (по значению, типа ID), ObjectKey (по объекту) и UniqueKey (уникальный, на один раз).
GlobalKey — это уже паспорт с визами. Действует во всём приложении, глобально. Зачем? Ну, например, чтобы из глубокого подвала кода достучаться до состояния какой-нибудь Form или Scaffold и сказать: «Эй, валидируйся!» или «Покажи snackbar!». Мощная штука, но дорогая — требует глобальной регистрации и может мусор не собираться, если неаккуратно использовать. С ним нужно, бля, аккуратнее, а то доверия ебать ноль к такой архитектуре.
Вот тебе живая аналогия, чтобы вообще ни хуя себе не осталось:
LocalKey— как твоя карточка в спортзале. Только в этом зале и работает. Кассирша (родитель) тебя по ней узнаёт.GlobalKey— как твой ИНН или паспорт. Можешь прийти в любую налоговую (любой виджет в приложении) и сказать: «Я вот этот человек, дайте доступ к моим данным (состоянию)».
Правило простое, ёпта: если можно обойтись LocalKey — используй его. GlobalKey — это как ядерная кнопка, только для особых случаев, когда реально нужно из другого конца приложения дернуть состояние. Иначе потом разбираться, почему всё накрылось медным тазом, — терпения ноль ебать.
Смотри, пример LocalKey в списке. Без него, если удалить элемент из середины, анимация может поехать, и фокус съедет.
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return ListTile(
// ValueKey помогает Flutter понять, что это за элемент.
// Без него он может по индексу только, а индекс-то меняется!
key: ValueKey(item.id),
title: Text(item.title),
);
},
)
А вот GlobalKey для формы. Классика, её все используют.
class MyForm extends StatelessWidget {
// Создаём ключ. Теперь он может достать состояние формы отовсюду.
final _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Form(
key: _formKey, // Вешаем ключ на форму
child: Column(
children: [
TextFormField(validator: (value) { /* ... */ }),
ElevatedButton(
onPressed: () {
// Вотана! Достаём состояние формы через ключ и командуем.
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// Данные улетели
}
},
child: Text('Отправить'),
),
],
),
);
}
}
Вот и вся магия. LocalKey — для порядка среди своих, GlobalKey — для тотального контроля из любой точки. Главное — не перепутай, а то будет тебе не оптимизация, а пиздопроебибна.