Разработка
Решаем проблему скелетных загрузчиков и создаем иллюзию скорости без перекомпозиции
С помощью всего лишь небольшой корректировки мы создали скелетный загрузчик, который обновляется плавно — не вызывая ненужных рекомпозиций.
Cкелетные загрузчики (Skeleton loader) играют важную роль в современном пользовательском опыте. Имитируя структуру контента, пока он еще загружается, они убеждают пользователей, что приложение работает, и помогают сократить воспринимаемое время ожидания. Но, несмотря на то, что они кажутся простым визуальным заполнителем, скелетные загрузчики часто под капотом скрывают тонкие и раздражающие проблемы.
В чем проблема?
Вы можете задаться вопросом, как загрузчик может быть сложным?
Проблема заключается в обработке параметра, который меняется очень часто — в данном случае это цвет, который анимируется между двумя состояниями (A → B → A), пока фактическое содержимое не будет готово к употреблению.
В ситуациях, когда значения часто меняются, хорошим правилом является передача их как лямбда-выражений.
Вместо того, чтобы передавать Color напрямую, передайте лямбда-выражение:
color: () -> Color
Этот подход дает нам больше контроля и позволяет избежать ненужных перекомпозиций.
Давайте рассмотрим простой пример того, как передать и использовать лямбда-функцию в композабл:
@Composable
fun SkeletonBox(
modifier: Modifier = Modifier,
color: () -> Color
) {
Box(
modifier = modifier
.fillMaxWidth()
.height(100.dp)
.background(color()) // this causes recompositions
)
}
Вы все еще можете заметить, что происходят рекомпозиции. Это потому, что использование Modifier.background(color()) запускает перекомпоновку каждый раз, когда изменяется значение цвета.
Однако, если мы рассмотрим поведение более внимательно, то единственным изменением будет цвет фона. В этом случае полная перекомпоновка не нужна — на самом деле нам нужна только перерисовка.
Чтобы добиться этого, мы можем вместо этого использовать Modifier.drawBehind {}. Этот модификатор выполняется во время фазы отрисовки, позволяя нам обновлять фон, не вызывая рекомпозиции.
Вот улучшенная реализация:
@Composable
fun OptimizedSkeletonBox(
modifier: Modifier = Modifier,
color: () -> Color
) {
Box(
modifier = modifier
.fillMaxWidth()
.height(100.dp)
.drawBehind {
drawRect(color())
}
)
}
Конечный результат: скелетный загрузчик с нулевыми рекомпозициями
С помощью всего лишь небольшой корректировки мы создали скелетный загрузчик, который обновляется плавно — не вызывая ненужных рекомпозиций. Результат не только выглядит великолепно, но и работает эффективно, что делает его надежным, переиспользуемым шаблоном для любых анимированных или часто обновляемых компонентов пользовательского интерфейса в вашем приложении.
-
Аналитика магазинов3 недели назад
Мобильный рынок Ближнего Востока: исследование Bidease и Sensor Tower выявляет драйверы роста
-
Интегрированные среды разработки4 недели назад
Chad: The Brainrot IDE — дикая среда разработки с играми и развлечениями
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.46
-
Видео и подкасты для разработчиков2 недели назад
Разбор кода: iOS-приложение для управления личными финансами на Swift. Часть 1

