Connect with us

Разработка

Решаем проблему скелетных загрузчиков и создаем иллюзию скорости без перекомпозиции

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

Опубликовано

/

     
     

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())
            }
    )
}

Конечный результат: скелетный загрузчик с нулевыми рекомпозициями

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

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: