В чем разница между методами requestLayout и invalidate
Что проверяют
Знаете ли вы, из каких фаз состоит отрисовка View и какую из них запускает каждый метод. Обычно следом просят написать сеттер для кастомной вью или спрашивают, что будет, если вызвать requestLayout() прямо в onLayout().
Как отвечать
Кадр в Android проходит три фазы: measure, layout, draw. Методы запрашивают разные из них:
invalidate(): помечает вью «грязной» и планирует перерисовку на следующий кадр. Вызываетсяdraw()и вашonDraw(), размеры и положение не пересчитываются. С аппаратным ускорением перезаписывается только display list этой вью, остальные переиспользуются. Вызывать нужно с главного потока, из фонового естьpostInvalidate();requestLayout(): ставит флаг принудительного лэйаута и поднимает запрос по цепочке родителей доViewRootImpl. На следующем кадре идёт проход measure и layout от корня,onMeasure()иonLayout()вызываются у помеченных вью, ветки без изменений отсекает кэш измерений. Перерисовка при этом не гарантирована: она случится, если изменились границы вью.
Отсюда практическое правило для кастомной вью. Свойство влияет только на внешний вид (цвет, прогресс, угол стрелки), вызывайте invalidate(). Меняет размер (текст, количество элементов, отступы), вызывайте requestLayout(), а если при том же размере меняется и картинка, добавьте invalidate().
Стандартные виджеты делают это сами: TextView.setText() уже запрашивает и лэйаут, и перерисовку, вручную там ничего вызывать не нужно. В Compose та же идея живёт в фазах composition, layout и drawing: состояние, прочитанное внутри drawBehind, перезапускает только отрисовку.
Где спотыкаются
Вызывают requestLayout() на каждое изменение, включая анимацию цвета. Каждый кадр превращается в проход measure и layout по дереву, и на сложном экране это заметно в профилировщике.
Считают, что requestLayout() сам вызовет onDraw(), и получают вью со старой картинкой, когда размер не изменился.
Дёргают requestLayout() изнутри onMeasure() или onLayout(). Система пишет в лог предупреждение о вызове во время лэйаута и откладывает его, а в худшем случае получается бесконечный цикл перекладки.