Что можно и нельзя делать в методе onDraw в Android
Что проверяют
Понимаете ли вы, что onDraw вызывается на главном потоке в каждом кадре, где view перерисовывается, и что любая лишняя работа в нём превращается в дёрганый интерфейс. Следом обычно просят написать простую кастомную view или спрашивают, куда тогда вынести подготовку.
Как отвечать
Начните с бюджета: при 60 Гц на кадр целиком около 16 мс, при 120 Гц около 8 мс, и onDraw лишь часть этой работы.
Что в onDraw делать нужно:
- только рисование: вызовы
CanvasвродеdrawRect,drawPath,drawText,drawBitmapпо заранее посчитанным данным; - работу с матрицей и клипом:
save()иrestore()парами,translate,rotate,clipRect.
Что делать нельзя:
- создавать объекты:
Paint,Path,Rect,Shader, строки. Каждый кадр даёт мусор для GC, lint прямо предупреждает об этом правиломDrawAllocation.Paintсоздают в конструкторе, геометрию считают вonSizeChanged, текст раскладывают черезStaticLayoutодин раз; - ввод-вывод и тяжёлые вычисления: чтение файлов, декодирование через
BitmapFactory, сеть. Это готовый ANR; - менять размеры:
requestLayout()изonDrawзапускает новый проход measure и layout на каждом кадре; - безусловно звать
invalidate(): view будет перерисовываться непрерывно и сажать батарею. Для анимации используютValueAnimatorилиpostInvalidateOnAnimation(), а перерисовку запрашивают только при изменении состояния.
В Compose тот же принцип: Modifier.drawBehind или Canvas, а объекты, которые зависят от размера, кешируются в Modifier.drawWithCache.
Где спотыкаются
Пишут val paint = Paint() прямо в onDraw, считая, что один маленький объект ничего не стоит. На списке или анимации это десятки аллокаций в секунду и заметные паузы.
Наследуют ViewGroup, переопределяют onDraw и не понимают, почему он не вызывается. У ViewGroup без фона по умолчанию выставлен флаг willNotDraw, нужен setWillNotDraw(false) или рисование в dispatchDraw.
Говорят, что invalidate() внутри onDraw вешает приложение бесконечным циклом. Зависания нет, вызов лишь планирует следующий кадр. Плоха постоянная перерисовка без причины.