廣西建設(shè)廳官方網(wǎng)站文件通知廣州網(wǎng)絡(luò)推廣策劃公司
做過布局性能優(yōu)化的同學(xué)都知道,為了優(yōu)化界面加載速度,要盡可能的減少布局的層級。這主要是因為布局層級的增加,可能會導(dǎo)致測量時間呈指數(shù)級增長。
而Compose卻沒有這個問題,它從根本上解決了布局層級對布局性能的影響: Compose界面只允許一次測量。這意味著隨著布局層級的加深,測量時間也只是線性增長的.
下面我們就一起來看看Compose到底是怎么只測量一次就把活給干了的,本文主要包括以下內(nèi)容:
- 布局層級過深為什么影響性能?
- Compose為什么沒有布局嵌套問題?
①布局層級過深為什么影響性能?
我們總說布局層級過深會影響性能,那么到底是怎么影響的呢?主要是因為在某些情況下ViewGroup會對子View進(jìn)行多次測量
舉個例子
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="match_parent"android:orientation="vertical"><Viewandroid:layout_width="match_parent"android:layout_height="100dp"android:background="@android:color/holo_red_dark" /><Viewandroid:layout_width="100dp"android:layout_height="100dp"android:background="@android:color/black" />
</LinearLayout>
- LinearLayout寬度為wrap_content,因此它將選擇子View的最大寬度為其最后的寬度
- 但是有個子View的寬度為match_parent,意思它將以LinearLayout的寬度為寬度,這就陷入死循環(huán)了
- 因此這時候, LinearLayout 就會先以0為強(qiáng)制寬度測量一下子View,并正常地測量剩下的其他子View,然后再用其他子View里最寬的那個的寬度,二次測量這個match_parent的子 View,最終得出它的尺寸,并把這個寬度作為自己最終的寬度。
- 這是對單個子View的二次測量,如果有多個子View寫了match_parent ,那就需要對它們每一個都進(jìn)行二次測量。
- 除此之外,如果在LinearLayout中使用了weight會導(dǎo)致測量3次甚至更多,重復(fù)測量在Android中是很常見的
上面介紹了為什么會出現(xiàn)重復(fù)測量,那么會有什么影響呢?不過是多測量了幾次,會對性能有什么大的影響嗎?
之所以需要避免布局層級過深是因為它對性能的影響是指數(shù)級的
-
如果我們的布局有兩層,其中父View會對每個子View做二次測量,那它的每個子View一共需要被測量 2 次
-
如果增加到三層,并且每個父View依然都做二次測量,這時候最下面的子View被測量的次數(shù)就直接翻倍了,變成 4 次
-
同理,增加到 4 層的話會再次翻倍,子 View 需要被測量 8 次
也就是說,對于會做二次測量的系統(tǒng),層級加深對測量時間的影響是指數(shù)級的,這就是Android官方文檔建議我們減少布局層級的原因
②Compose為什么沒有布局嵌套問題?
我們知道,Compose只允許測量一次,不允許重復(fù)測量。
如果每個父組件對每個子組件只測量一次,那就直接意味著界面中的每個組件只會被測量一次
這樣即使布局層級加深,測量時間卻沒有增加,把組件加載的時間復(fù)雜度從O(2?) 降到了 O(n)。
那么問題就來了,上面我們已經(jīng)知道,多次測量有時是必要的,但是為什么Compose不需要呢?
Compose中引入了固有特性測量(Intrinsic Measurement)
固有特性測量即Compose允許父組件在對子組件進(jìn)行測量之前,先測量一下子組件的「固有尺寸」
我們上面說的,ViewGroup的二次測量,也是先進(jìn)行這種「粗略測量」再進(jìn)行最終的「正式測量」,使用固有特性測量可以產(chǎn)生同樣的效果
而使用固有特性測量之所以有性能優(yōu)勢,主要是因為其不會隨著層級的加深而加倍,固有特性測量也只進(jìn)行一次
Compose會先對整個組件樹進(jìn)行一次Intrinsic測量,然后再對整體進(jìn)行正式的測量。這樣開辟兩個平行的測量過程,就可以避免因為層級增加而對同一個子組件反復(fù)測量所導(dǎo)致的測量時間的不斷加倍了。
總結(jié)成一句話就是,在Compose里瘋狂嵌套地寫界面,和把所有組件全都寫進(jìn)同一層里面,性能是一樣的!所以Compose沒有布局嵌套問題
Android 學(xué)習(xí)筆錄
Kotlin 篇:https://qr18.cn/CdjtAF
Android 性能優(yōu)化篇:https://qr18.cn/FVlo89
Android 車載篇:https://qr18.cn/F05ZCM
Android Framework底層原理篇:https://qr18.cn/AQpN4J
Android 音視頻篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(內(nèi)含Compose):https://qr18.cn/A0gajp
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源碼解析筆記:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知識體:https://qr18.cn/CyxarU
Android 核心筆記:https://qr21.cn/CaZQLo
Android 面試題錦:https://qr18.cn/CKV8OZ