Что такое PageStorageKey в Flutter?

Ответ

PageStorageKey — это специальный тип ValueKey, который используется в паре с виджетом PageStorage для идентификации и сохранения состояния конкретного виджета (чаще всего позиции скролла).

Назначение: Связывает состояние виджета (данные) с уникальным идентификатором в PageStorageBucket. Это позволяет Flutter понять, какое состояние принадлежит какому виджету, особенно когда виджет уничтожается и создается заново.

Синтаксис и использование:

// Для простых случаев можно использовать строку
const PageStorageKey<String>('my_unique_list_key')

// Или любой другой comparable-объект в качестве значения
PageStorageKey<int>(42)
PageStorageKey<MyClass>(myInstance) // где MyClass реализует == и hashCode

Типичный сценарий применения со Scrollable виджетами:

CustomScrollView(
  key: const PageStorageKey('home_feed_scroll'),
  slivers: [
    SliverList(...),
  ],
)
// При возврате на этот экран позиция скролла восстановится автоматически.

Ключевые моменты:

  • Уникальность: Ключ должен быть уникальным в рамках одного PageStorageBucket (обычно в рамках одного маршрута/Route) для разных сохраняемых виджетов. Иначе состояния могут перепутаться.
  • Типизация: Использование дженерика (PageStorageKey<T>) помогает избежать случайных коллизий ключей разных типов.
  • Не для всех виджетов: В основном используется со ListView, GridView, CustomScrollView и другими прокручиваемыми виджетами, но может применяться и для сохранения другого простого состояния.

Без PageStorageKey скроллящиеся виджеты при повторной инициализации начинали бы с позиции 0.0.

Ответ 18+ 🔞

Да ты посмотри, какая хитрая штука этот PageStorageKey! Ну в общем, представляешь, это такой специальный пацан из семейства ValueKey, который работает заодно с виджетом PageStorage. Их главная фишка — они как будто вешают бирочку на состояние какого-нибудь виджета (ну, чаще всего на позицию скролла, конечно) и прячут эту бирочку в специальное ведро — PageStorageBucket. А потом, когда виджет нахуй сносит и собирают заново, Flutter смотрит в это ведро, находит по бирочке сохранённые данные и говорит: «А, так это ж твои, на, держи!». Без этого всё начиналось бы с нуля каждый раз, ёпта.

Как этим пользоваться, чтобы не облажаться:

// Можно просто строку впихнуть, главное, чтобы уникальная была
const PageStorageKey<String>('ключ_от_моей_длиннющей_ленты')

// Или вообще что угодно, что можно сравнивать (comparable)
PageStorageKey<int>(42)
PageStorageKey<MyClass>(myInstance) // если в MyClass == и hashCode прописаны

Где это обычно впендюривают (прям классика):

CustomScrollView(
  key: const PageStorageKey('home_feed_scroll'), // Вот она, волшебная палочка!
  slivers: [
    SliverList(...),
  ],
)
// Ушёл с экрана, вернулся — а скролл на том же месте, где и был! Магия, блядь.

А теперь главное, что надо помнить, а то будет пиздец:

  • Уникальность — наше всё: Ключ должен быть как отпечаток пальца в рамках одного PageStorageBucket (это обычно один маршрут). Если для двух разных списков сделать одинаковый ключ — они начнут делить одно состояние, и получится ебанько полная. Один будет скроллиться, а второй за ним повторять.
  • Типизация — не просто так: Дженерик (PageStorageKey<T>) — это не для красоты. Он помогает, чтобы ключ-строка случайно не сцепился с ключом-числом, если они одинаково выглядят. Удивление пиздец будет, когда всё сломается.
  • Не только для скролла: Да, чаще всего его цепляют на ListView, GridView, CustomScrollView, чтобы позицию не терять. Но вообще-то можно и любое другое простое состояние виджета сохранять, если очень захотеть.

Короче, без этого PageStorageKey твой скролл каждый раз как новорождённый — начинает жизнь с самого верха, с позиции 0.0. А так — всё помнит, хитрая жопа. Главное, ключи не перепутай, а то вместо ленты новостей будешь восстанавливать позицию в настройках, ядрёна вошь.