Как подойти к реализации кастомного лоадера с анимацией
Что проверяют
Под «лоадером» здесь почти всегда имеют в виду индикатор загрузки, а не класс Loader для данных. Проверяют, умеете ли вы сделать анимированный компонент, который не нагружает главный поток, корректно живёт в жизненном цикле и доступен. Следом спрашивают, как вы убедитесь, что анимация не теряет кадры.
Как отвечать
Сначала уточните стек: Compose или View. Затем варианты от простого к сложному:
- готовое:
CircularProgressIndicatorиз Material 3 с кастомными цветами и толщиной закрывает большинство задач; - Compose: свой
CanvasсdrawArc, а угол дуги анимируетrememberInfiniteTransitionсanimateFloatиinfiniteRepeatable. Значение читайте в фазе отрисовки, внутриCanvasилиgraphicsLayer, тогда кадр не вызывает рекомпозицию; - View: наследник
Viewс переопределённымonDraw, объектыPaintиPathсоздаются заранее. Анимацию ведётValueAnimator, который вызываетinvalidate(). Запускать вonAttachedToWindow, останавливать вonDetachedFromWindowи при скрытии; - векторные:
AnimatedVectorDrawableдля анимации пути из дизайна или Lottie, если дизайнер отдаёт анимацию из After Effects; - состояние: лоадер показывается по
UiStateиз ViewModel, а не по флагам в разных местах. Короткие загрузки не должны мигать индикатором: нужна задержка показа и минимальное время отображения.
Упомяните доступность: contentDescription или semantics с progressBarRangeInfo, и уважение к системной настройке масштаба анимаций. Плавность проверяют через Perfetto или Macrobenchmark с FrameTimingMetric.
Где спотыкаются
Рассказывают про AsyncTaskLoader и LoaderManager. Этот API объявлен устаревшим с Android 9, загрузка данных сейчас живёт в ViewModel с корутинами и Flow.
Создают объекты в onDraw или гоняют анимацию через рекомпозицию на каждом кадре. В результате сборщик мусора срабатывает посреди анимации, и она дёргается.
Не останавливают бесконечную анимацию, когда View ушла с экрана. Аниматор держит ссылку на View и продолжает тратить батарею.