Режим сильного пропуска

Строгий пропуск — это режим, доступный в компиляторе Compose. Если этот параметр включен, он меняет поведение компилятора двумя способами:

Включить режим сильного пропуска

В Kotlin 2.0.20 сильный пропуск включен по умолчанию.

Чтобы включить строгий пропуск для модуля Gradle в предыдущей версии, включите следующую опцию в блок composeCompiler вашей конфигурации Gradle:

android { ... }

composeCompiler {
   enableStrongSkippingMode = true
}

Компонуемая возможность пропуска

Режим строгого пропуска ослабляет некоторые правила стабильности, обычно применяемые компилятором Compose, когда дело касается пропуска и компонуемых функций. По умолчанию компилятор Compose помечает составную функцию как пропускаемую, если все ее аргументы имеют стабильные значения. Режим сильного пропуска меняет это.

Если включен строгий пропуск, все перезапускаемые составные функции становятся пропускаемыми. Это применимо независимо от того, имеют ли они нестабильные параметры. Неперезапускаемые составные функции остаются непропускаемыми.

Когда пропустить

Чтобы определить, следует ли пропускать компоновку во время рекомпозиции, Compose сравнивает значение каждого параметра с их предыдущими значениями. Тип сравнения зависит от стабильности параметра.

  • Нестабильные параметры сравниваются с использованием равенства экземпляров ( === ).
  • Стабильные параметры сравниваются с использованием равенства объектов ( Object.equals() ).

Если все параметры соответствуют этим требованиям, Compose пропускает компонуемый объект во время рекомпозиции.

Возможно, вы захотите, чтобы составной элемент отказался от сильного пропуска. То есть вам может понадобиться перезапускаемый, но не пропускаемый составной элемент. В этом случае используйте аннотацию @NonSkippableComposable .

@NonSkippableComposable
@Composable
fun MyNonSkippableComposable {}

Аннотировать классы как стабильные

Если вы хотите, чтобы объект использовал равенство объектов вместо равенства экземпляров, продолжайте аннотировать данный класс с помощью @Stable. Примером того, когда вам может потребоваться это сделать, является просмотр всего списка объектов. Источники данных, такие как Room, будут выделять новые объекты для каждого элемента в списке каждый раз, когда один из них изменяется.

Лямбда-мемоизация

Режим сильного пропуска также позволяет лучше запоминать лямбды внутри компонуемых объектов. Если включен строгий пропуск, каждая лямбда внутри составной функции будет автоматически запоминаться.

Примеры

Чтобы добиться запоминания лямбда-выражений внутри компонуемых объектов при использовании сильного пропуска, компилятор оборачивает вашу лямбду вызовом remember . Он связан с захватами лямбды.

Рассмотрим случай, когда у вас есть лямбда, как в следующем примере:

@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
    val lambda = {
        use(unstableObject)
        use(stableObject)
    }
}

При включенном строгом пропуске компилятор запоминает лямбду, заключая ее в вызов remember :

@Composable
fun MyComposable(unstableObject: Unstable, stableObject: Stable) {
    val lambda = remember(unstableObject, stableObject) {
        {
            use(unstableObject)
            use(stableObject)
        }
    }
}

Ключи следуют тем же правилам сравнения, что и составные функции. Среда выполнения сравнивает нестабильные ключи, используя равенство экземпляров. Он сравнивает стабильные ключи, используя равенство объектов.

Мемоизация и рекомпозиция

Эта оптимизация значительно увеличивает количество компонуемых объектов, которые среда выполнения пропускает во время рекомпозиции. Без мемоизации среда выполнения с гораздо большей вероятностью выделит новую лямбду для любого составного объекта, который принимает параметр лямбда во время рекомпозиции. В результате новая лямбда имеет параметры, не равные последней композиции. Это приводит к рекомпозиции.

Избегайте мемоизации

Если у вас есть лямбда-выражение, которое вы не хотите запоминать, используйте аннотацию @DontMemoize .

val lambda = @DontMemoize {
    ...
}

Размер APK

При компиляции компонуемые элементы с возможностью пропуска приводят к созданию большего количества кода, чем составные элементы, которые не могут быть пропущены. При включенном строгом пропуске компилятор помечает почти все составные элементы как пропускаемые и оборачивает все лямбды в remember{...} . В связи с этим включение режима строгого пропуска очень незначительно влияет на размер APK вашего приложения.

Включение сильного пропуска в Now In Android увеличило размер APK на 4 КБ. Разница в размере во многом зависит от количества ранее не пропускаемых составных элементов, которые присутствовали в данном приложении, но должна быть относительно незначительной.