导致View树遍历的时机
遍歷View樹意味著整個(gè)View需要重新對(duì)其包含的子視圖分配大小并重繪,導(dǎo)致重新遍歷的原因主要有三個(gè)
1.視圖本身內(nèi)部狀況變化引起重繪。
2.第二個(gè)是View樹內(nèi)部添加或者刪除了View。
3.View本身的大小及可見性發(fā)生變化。
能引起View樹重新遍歷的操作,總的來講可以分為三類。一類是導(dǎo)致視圖大小發(fā)生變化;第二類是導(dǎo)致ViewGroup重新為子視圖分配位置;第三類是視圖顯示情況發(fā)生變化需要重繪。這三類情況最后都直接或者間接調(diào)用到三個(gè)函數(shù),分別為invalidate()、requesetLayout()及requestFocus(),而這三個(gè)函數(shù)最終都會(huì)調(diào)用到ViewRoot中的schuedeuleTravesals()函數(shù),該函數(shù)然后發(fā)起一個(gè)異步消息,消息處理中調(diào)用performTraversals()開始對(duì)整個(gè)View進(jìn)行重新遍歷。
能導(dǎo)致調(diào)用invalidate()函數(shù)的包含三種情況:
1、當(dāng)應(yīng)用程序改變視圖顯示屬性時(shí),調(diào)用setVisibility()。
2、當(dāng)改變視圖Selected狀態(tài)時(shí),調(diào)用setSelected()。
3、當(dāng)改變視圖Enable狀態(tài)時(shí),調(diào)用setEnable()函數(shù)。
能導(dǎo)致調(diào)用requestLayout()函數(shù)的情況包含兩種:
1、當(dāng)應(yīng)用程序改變視圖顯示屬性時(shí),調(diào)用setVisibility(),由于顯示或者不顯示將影響其他兄弟視圖的位置,因 此會(huì)調(diào)用到requestLayout()。
2、應(yīng)用程序直接或間接調(diào)用該函數(shù),間接調(diào)用是指應(yīng)用程序調(diào)用了View類的其他函數(shù),從而間接調(diào)用到requestLayout()。
requestFocus()一般由程序直接調(diào)用。
refreshDrawableList()
該函數(shù)的作用是根據(jù)狀態(tài)標(biāo)識(shí),為視圖賦予不同的Drawable對(duì)象。
1、給mPrivateFlags添加DRAWABLE_STATE_DIRTY標(biāo)識(shí),該標(biāo)識(shí)僅在后面調(diào)用getDrawableState()函數(shù)中用于判斷是否發(fā)生狀態(tài)變化。
2、調(diào)用drawableSateChanged()。該函數(shù)是一個(gè)protected類型,只有Framework中的View子類可以重載該函數(shù),一般來講,就是ViewGroup重載了該函數(shù)。ViewGroup中重載該函數(shù)的作用僅僅是為了配合FLAG_ADD_STATES_FROM_CHILDRN標(biāo)識(shí),后面將會(huì)講到該標(biāo)識(shí)的作用。View類內(nèi)部,該函數(shù)的默認(rèn)實(shí)現(xiàn)包括以下幾項(xiàng)。
(1)調(diào)用getDrawableState()獲得視圖的當(dāng)前狀態(tài),然后再調(diào)用onCreateDrawableState()將這些狀態(tài)轉(zhuǎn)換為一個(gè)int[]型數(shù)組,這個(gè)數(shù)組的內(nèi)部格式是預(yù)先定好的,DrawableStateList類可以識(shí)別該int[]數(shù)組。最后再將第一步設(shè)置的標(biāo)識(shí)進(jìn)行清除。
(2)mBGDrawable變量是該視圖的背景圖,它包含一個(gè)setState()函數(shù),函數(shù)的參數(shù)正是上一步獲得的int[]型數(shù)組,該函數(shù)內(nèi)部會(huì)根據(jù)該int[]型數(shù)組為mBGDrawable找到真正的Drawable對(duì)象。
3、如果該視圖有父視圖,則調(diào)用父視圖的childDrawableStateChanged()。父視圖要么是ViewGroup類,要么是一個(gè)ViewRoot類。
ensureTouchMode()
這個(gè)函數(shù)的命名不夠準(zhǔn)確,從該函數(shù)內(nèi)部分析來看,其作用是在Touch和非Touch直接切換時(shí)對(duì)視圖的焦點(diǎn)狀態(tài)進(jìn)行處理。
setVisibility()
該函數(shù)用于改變視圖的可視狀態(tài),可視狀態(tài)包括GONE、VISIBLE、INVSIBLE三種。該函數(shù)內(nèi)部很簡(jiǎn)單,首先調(diào)用setFlags(),然后調(diào)用mBGDrawable.setVisible()函數(shù)改變視圖背景圖的顯示狀態(tài)。
setEnable()
Enable狀態(tài)僅僅是內(nèi)部的一個(gè)邏輯,不會(huì)引起重新布局,僅僅是引起視圖的重繪。
1、給mPrivateFlags變量添加ENABLE或者DISABLE標(biāo)識(shí),這由setEnalbe()的參數(shù)決定。
2、調(diào)用refreshDrawableState()重新獲取背景圖。
3、調(diào)用invalidate()請(qǐng)求View樹重繪。
invalidate()
該函數(shù)的作用是請(qǐng)求View樹進(jìn)行重繪,當(dāng)應(yīng)用程序需要重繪某個(gè)視圖時(shí),可以調(diào)用該函數(shù)。大致做了兩件事情。
1、給所有需要重繪的視圖添加了一個(gè)DIRTY或者DIRTY_OPAQUE標(biāo)記。
2、通過矩形運(yùn)算,找到真正需要重繪的矩形區(qū),并將其保存在了ViewRoot類中的mDirty變量中。
requestFocus()
要想讓某個(gè)視圖獲得焦點(diǎn)
1、用戶使用方向鍵將焦點(diǎn)移動(dòng)到該視圖(其實(shí)也是調(diào)用requestFocus()函數(shù)完成)。
2、直接調(diào)用視圖的requestFocus()函數(shù)。
下面分析requestFocus(direction, preFocusRect)的執(zhí)行過程:
1、判斷該視圖是不是FOCUSABLE的,如果不是,則直接返回false。
2、如果當(dāng)前是Touch模式,但是視圖的FOCUSABLE_IN_TOUCH_MODE卻為false,即該視圖不能在Touch模式下獲得焦點(diǎn),則直接返回false。
3、調(diào)用hasAncestorThatBlockDescendantFocus()判斷是否父視圖阻止該子視圖獲得焦點(diǎn),如果阻止,則直接返回false。應(yīng)用程序可以調(diào)用ViewGoup的setDescendantFocusability(int focusability)方法設(shè)置該ViewGroup是否阻止其子視圖獲得焦點(diǎn),默認(rèn)情況下都不阻止。
4、以上三步實(shí)際上執(zhí)行的都是前期檢查,調(diào)用handleFocusGainInternal(dir, rect)進(jìn)行具體的焦點(diǎn)獲取操作,執(zhí)行完該函數(shù)后,則該視圖肯定獲取焦點(diǎn),所以返回true。
requestLayout()
該函數(shù)的執(zhí)行過程比較簡(jiǎn)單,因?yàn)楫?dāng)View樹進(jìn)行重新布局時(shí),總是重新給所有的視圖進(jìn)行布局,因?yàn)?#xff0c;最簡(jiǎn)單的想法就是只要設(shè)置一個(gè)標(biāo)識(shí)就好。
首先給mPrivateFlags添加FORCE_LAYOUT標(biāo)識(shí),然后調(diào)用mParent的requestLayout()函數(shù)。
1、調(diào)用checkThread()確保本次調(diào)用是在UI線程中執(zhí)行的,非UI線程執(zhí)行該函數(shù)將導(dǎo)致狀態(tài)管理的混亂,并最終crash掉。
2、給ViewRoot中的變量mLayoutRequested賦值為true,之后真正進(jìn)行布局的代碼將檢查該變量,并決定是否需要重新布局。
3、調(diào)用scheduleTraversals()發(fā)起一個(gè)View樹遍歷的消息,該消息是異步處理的,對(duì)應(yīng)的處理函數(shù)是performTraversals()。
總結(jié)
以上是生活随笔為你收集整理的导致View树遍历的时机的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 女人梦到大蛇预示着什么意思
- 下一篇: 梦到家里着火是什么意思