Strong Skipping (Строгий Пропуск) - это режим, доступный в компиляторе Compose. Когда он включен, он меняет поведение компилятора двумя способами:
- Компонуемые функции (Composables) с нестабильными параметрами становятся пропускаемыми (skippable)
- Лямбды с нестабильными захватами запоминаются (
remember {})
Режим строгого пропуска ослабляет некоторые правила стабильности, которые обычно применяются компилятором Compose в отношении пропуска и компонуемых функций. По умолчанию компилятор Compose помечает компонуемую функцию как пропускаемую (skippable), только если все её аргументы имеют стабильные значения. Режим строгого пропуска меняет это поведение.
Когда включен строгий пропуск, все перезапускаемые (restartable) компонуемые функции становятся пропускаемыми (skippable). Это применяется независимо от того, имеют ли они нестабильные параметры. Неперезапускаемые компонуемые функции остаются непропускаемыми.
- Skippable (Пропускаемые): Если компилятор помечает компонент как пропускаемый, Compose может пропустить его во время рекомпозиции, если все его аргументы равны их предыдущим значениям.
- Restartable (Перезапускаемые): Компонент, который является перезапускаемым, служит "областью", с которой может начаться рекомпозиция. Другими словами, функция может быть точкой входа, с которой Compose может начать повторное выполнение кода для рекомпозиции после изменения состояния.
Чтобы определить, следует ли пропустить компонуемую функцию во время перекомпозиции, Compose сравнивает значение каждого параметра с их предыдущими значениями. Тип сравнения зависит от стабильности параметра:
- Нестабильные (unstable) параметры сравниваются с помощью равенства экземпляров (
===) - Стабильные (stable) параметры сравниваются с помощью равенства объектов (
Object.equals())
Если все параметры соответствуют этим требованиям, Compose пропускает компонуемую функцию во время перекомпозиции.
Может быть случай, когда строгий пропуск не нужен. То есть, вам может понадобиться перезапускаемая (restartable), но не пропускаемая (non-skipping) компонуемая функция. В этом случае используйте аннотацию @NonSkippableComposable.
@NonSkippableComposable
@Composable
fun MyNonSkippableComposable(){}Если вы хотите, чтобы объект использовал равенство объектов (Object.equals()) вместо равенства экземпляров (===), продолжайте помечать соответствующий класс аннотацией @Stable. Пример, когда это может понадобиться - при наблюдении за целым списком объектов, источники данных, такие как Room, будут создавать новые объекты для каждого элемента в списке каждый раз, когда один из них изменяется.
Режим строгого пропуска также позволяет лучше запоминать лямбды внутри компонуемых функций. Когда включен строгий пропуск, каждая лямбда внутри компонуемой функции будет автоматически запоминаться.
-
- Создаётся без remember → экземпляр новый каждый раз.
- Внутри — тривиальная операция (x.isNotEmpty(), a+b) → накладные расходы больше пользы.
- Входы меняются на каждый кадр или на каждую рекомпозицию (анимации, быстрые счётчики) → кэш не используется.
- Уже есть remember с корректными ключами, и вычисление выполняется ровно при изменении этих ключей.
-
- Immutable — это объект, который после создания гарантированно никогда не меняется: все его публичные свойства — val без скрытой мутации, а их типы — примитивы или тоже Immutable. Компилятор Compose может полностью доверять такому объекту и безопасно пропускать рекомпозиции, потому что значение в нём никогда не изменится.
- Stable — это объект, который может изменяться, но обязуется делать это предсказуемо: изменения его публичных свойств всегда уведомляют Compose, equals работает стабильно, а все публичные свойства сами являются стабильными типами. Такой объект допускает оптимизации, но не столь агрессивные, как Immutable, потому что его состояние всё же может меняться.