В зависимости от результата Composition, Compose Composition запускает этапы Composition и Composition. Эти этапы могут быть пропущены, если контент не изменился, и, следовательно, общий размер элементов не изменится.
Этап 2:Этап 2:.
Этап Layout включает два шага: измерение и размещение. Шаг измерения запускает лямбда-функции измерения, переданные в Layout, метод Layout.measure интерфейса Layout. Размещение запускает блок функции Layout, лямбду из Layout.LayoutLayout и т.д.
Считывание состояний во время каждого шага затрагивает этапы Layout и, потенциально, Layout. Когда значение состояния меняется, Layout планирует выполнение этапа Layout. Это также запускает этап Layout, если размер или расположение изменились.
Если быть более точным, шаги измерения и размещения имеют различные области перезапуска. То есть изменение прочитанного состояния на шаге размещения не вызывает повторно шаг измерения, который шел раньше. Однако эти два шага часто взаимосвязаны, так что чтение состояния на шаге размещения может повлиять на области перезапуска, которые относятся к шагу измерения.
Этап 3:Этап 3:.
Чтение состояния внутри кода отрисовки влияет на этап Drawing. Распространенные примеры включают: Drawing, Drawing.Drawing и Drawing.Drawing. Когда значение считанного на этом этапе состояния меняется, Drawing запускает только этап Drawing.
Оптимизация считывания состояния. Поскольку Compose выполняет отслеживание считывания состояний внутри этапов, мы можем минимизировать количество работы, выполняемой считыванием каждого состояния на этапах.
Посмотрим на пример ниже. У нас есть Image, который использует ImageImage для смещения своего положения. В результате во время скроллинга пользователь наблюдает эффект параллакса за счет добавления Image. Этот код работает, но дает неоптимальную производительность.
По мере прокрутки пользователем значение firstVisibleItemScrollOffset будет меняться. Как мы знаем, firstVisibleItemScrollOffset отслеживает любое чтение состояния, чтобы можно было повторно вызвать считывающий этот состояние код, в нашем случае содержимое firstVisibleItemScrollOffset.
В этом примере состояние читается внутри этапа Composition. Это необязательно плохо. Фактически это основа рекомпозиции, позволяющая при изменении данных создавать новый UI. Причина не оптимальности кода в примере выше в том, что каждое событие скролла приводит к переоценке всего существующего composable-composable-, и затем новому измерению, расположению и финальной отрисовке.
Мы запускаем этап Composition на каждую прокрутку, даже если то, что мы показываем, не изменилось, а изменилось только где показываем. Мы можем оптимизировать считывание нашего состояния, чтобы повторно запускать этапы, начиная с Layout.
Существует другая версия offsetoffset. Эта версия функции принимает лямбду, которая возвращает итоговый offset.
Почему этот способ более производительный? Лямбда, которую мы предоставляем модификатору, вызывается во время этапа Layout если быть точнее, во время шага размещения что означает, что наше состояние Layout больше не считывается во время этапа Layout. Compose отслеживает, когда состояние считано. Поэтому, если значение Layout меняется, Compose должен только перезапустить этапы Layout и Layout.
Вы можете спросить: не может ли использование лямбды привести к дополнительным затратам по сравнению с использованием простого значения? Так и есть. Однако выигрыш от чтения состояния на этапе Layout перевешивает эти затраты. Значение Layout меняет каждый кадр в течение прокрутки, и, отложив чтение состояния до этапа Layout, мы совсем избегаем повторных этапов Layout.
Layouts
Основными layout в layout являются layout. Также layout позволяет использовать аналоги layoutlayout. Все эти компоненты layoutlayout функции. Это значит, что другие layout функции могут быть вызваны внутри них.