android 系統回調onSizeChange, onMeasure, onLayout調用時機-LotusLoveNature
最新項目中常用到上面三個系統回調,所以就在想,這三個用的時機到底是怎么樣的?今天做了實驗:
<?xml version="1.0" encoding="utf-8"?>
<com.lotus.measure.ReSizeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.lotus.measure.MyEditText
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<com.lotus.measure.MyLinearLayout
android:id="@+id/bottom_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom"
android:orientation="vertical" >
<Button
android:id="@+id/button"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:text="haha" >
</Button>
<com.lotus.measure.MyTextView
android:id="@+id/textview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#77777777"
android:text="hello" />
</com.lotus.measure.MyLinearLayout>
</com.lotus.measure.ReSizeLayout>
按照上面的層次關系,每個view自定義一下,就是為了將三個方法打印出來,打印結果:
01-19 17:17:44.985: I/cdd(15351): ReSizeLayout--------onSizeChanged--480,741,0,0
01-19 17:17:44.985: I/cdd(15351): MyEditText--------onSizeChanged--480,65,0,0
01-19 17:17:44.985: I/cdd(15351): MyEditText--------onLayout--0,0,480,65
01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onSizeChanged--480,676,0,0
01-19 17:17:44.985: I/cdd(15351): MyTextView--------onSizeChanged--480,25,0,0
01-19 17:17:44.985: I/cdd(15351): MyTextView--------onLayout--0,651,480,676
01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onLayout--0,65,480,741
01-19 17:17:44.985: I/cdd(15351): ReSizeLayout--------onLayout--0,0,480,741
01-19 17:17:44.985: I/cdd(15351): MyEditText--------onMeasure--480,741
01-19 17:17:44.985: I/cdd(15351): MyTextView--------onMeasure--480,526
01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onMeasure--480,676
01-19 17:17:44.985: I/cdd(15351): ReSizeLayout--------onMeasure--480,741
01-19 17:17:44.985: I/cdd(15351): MyEditText--------onLayout--0,0,480,65
01-19 17:17:44.985: I/cdd(15351): MyTextView--------onLayout--0,651,480,676
01-19 17:17:44.985: I/cdd(15351): MyLinearLayout--------onLayout--0,65,480,741
01-19 17:17:44.995: I/cdd(15351): ReSizeLayout--------onLayout--0,0,480,741
感覺執行順序是這樣的:
1. 首先是執行葉子child的onMeasure方法,逐層向上調用,最后調用到root的onMeasure,onMeasure本身的作用就是告訴父親自己占用多大的位置,根據遞歸原理,onMeasure的確應該從下往上層調用
2. 調用到root的onMeasure后,其實這個統計大小的工作肯定是比root還高級別的View觸發,也許就是DecorView,統計完大小后,開始調用onSizeChange,我想這里調用onSizeChange是因為首次顯示的原因,調用onSizeChange是從root開始的,然后逐級調用到child,調用每個child的onSizeChange完畢后,每個child執行layout動作
3. 從順序來看,layout動作和onMeasure一樣,都是從小往上層調用。從葉子child的onlayout調用開始,最后調用到root的onlayout方法。因為只有大小發生了變化才會執行onSizeChange,所以沒有onSizeChange的時候,就是從尾到頭執行完onmeasure,再開始從尾到頭執行完onlayout
4. 由此看來,onSizeChange並不一定會調用,只有View的大小發生變化才會調用,而且也不一定一定從root開始調用。onMeasure在整個界面上需要放置一樣東西或拿掉一樣東西時會調用。比如addView就是放置,removeview就是拿掉,另外比較特殊的是,child設置為gone會觸發onMeasure,但是invisible不會觸發onMeasure。一旦執行過onMeasure,往往就會執行onLayout來重新布局
5. 分支影響整個分支直到root,比如上面的root有兩個孩子,這兩個孩子是不同的分支,這兩個孩子是同級別,如果又孩子在點擊button的時候讓textview消失掉
01-19 17:40:56.185: I/cdd(15481): MyLinearLayout--------onMeasure--480,676
01-19 17:40:56.185: I/cdd(15481): ReSizeLayout--------onMeasure--480,741
01-19 17:40:56.185: I/cdd(15481): MyLinearLayout--------onLayout--0,65,480,741
01-19 17:40:56.185: I/cdd(15481): ReSizeLayout--------onLayout--0,0,480,741
它會影響右分支所有直到root,所以同一分支比較容易影響。但是我們看到沒有影響到左孩子
為什么沒有影響到做孩子呢,是因為沒有影響到他的大小或者位置。
比如,在root下面加入一個孩子,如果孩子是加在前面兩個孩子后面,那么對前面兩個孩子都沒有影響。但是如果加在兩個孩子中間,那么對第二個孩子影響,影響的話就會執行onmeasure和onlayout
a.加在兩個孩子后面
01-19 17:53:53.235: I/cdd(15939): ReSizeLayout--------onMeasure--480,741
01-19 17:53:53.235: I/cdd(15939): ReSizeLayout--------onLayout--0,0,480,741
b.加在兩個孩子中間
01-19 17:45:55.345: I/cdd(15846): MyTextView--------onMeasure--480,454
01-19 17:45:55.345: I/cdd(15846): MyLinearLayout--------onMeasure--480,604
01-19 17:45:55.345: I/cdd(15846): ReSizeLayout--------onMeasure--480,741
01-19 17:45:55.345: I/cdd(15846): MyLinearLayout--------onSizeChanged--480,604,480,676
01-19 17:45:55.345: I/cdd(15846): MyTextView--------onLayout--0,579,480,604
01-19 17:45:55.345: I/cdd(15846): MyLinearLayout--------onLayout--0,137,480,741
01-19 17:45:55.345: I/cdd(15846): ReSizeLayout--------onLayout--0,0,480,741
6. 一個分支下的影響很可能就是一條線到root,同級別的影響先決條件是,改變同級的大小或者位置,有時候沒有改變大小或者位置,也可能調用