Зачем нужен метод forceLayout
Что проверяют
Понимаете ли вы, как устроены проходы measure и layout в системе View и чем forceLayout() отличается от requestLayout(). Вопрос с подвохом: многие считают forceLayout() «более сильным» requestLayout(), а на деле он слабее. Следом обычно спрашивают, зачем он тогда вообще нужен.
Как отвечать
Разберите оба метода:
requestLayout(): помечает View флагом «нужен layout», поднимается по цепочке родителей доViewRootImplи планирует обход дерева на ближайший кадр;forceLayout(): ставит тот же флаг, но только на этом View. Родителям ничего не сообщает и обход не планирует, поэтому сам по себе вызов ничего на экране не меняет;- зачем флаг:
measure()пропускаетonMeasure(), еслиMeasureSpecне изменился, и может взять размер из кэша измерений. Флаг принудительного layout обходит эту оптимизацию, и на следующем проходе View перемерится обязательно.
Отсюда сценарий. Вы пишете свой ViewGroup и знаете, что содержимое дочернего View изменилось, а ограничения, которые вы ему передадите, останутся прежними. Вы вызываете forceLayout() на ребёнке и requestLayout() на себе, и на следующем проходе ребёнок честно пересчитает размер. Этим пользуются и классы фреймворка, например AbsListView для своих дочерних и переиспользуемых View.
В Jetpack Compose прямого аналога нет: перемер запускается сам, когда меняется состояние, прочитанное на этапе measure.
Где спотыкаются
Говорят, что forceLayout() немедленно пересчитывает всю иерархию. Он ничего не делает немедленно и не трогает другие View.
Вызывают forceLayout() вместо requestLayout(), когда View поменяла размер, и не понимают, почему экран не обновился.
Путают layout с отрисовкой: для смены внешнего вида без смены размеров нужен invalidate(), а лишний requestLayout() на каждом кадре анимации запускает дорогие проходы measure и layout по дереву.