Window
- Window是View的直接管理者导坟,所有的視圖都是通過Window這一塊呈現(xiàn)
- Window是頂級抽象基類,唯一實(shí)現(xiàn)類是PhoneWindow圈澈,作為頂級View會添加到Window Manager中
- 每一個Activity都包含一個Window實(shí)例惫周,即PhoneWindow,其中Activity的setContentView的方法是調(diào)用PhoneWindow的setContentView方法
- PhoneWindow中包含成員變量DecorView(FrameLayout)康栈,此頂級View內(nèi)部包含一個豎直方向的LinearLayout递递,上面的標(biāo)題欄(titleBar),下面是內(nèi)容欄啥么。通常我們在Activity中通過setContentView所設(shè)置的布局文件就是被加載到LinearLayout中id為android.R.id.content的內(nèi)容欄里(FrameLayout登舞,即mContentParent)
Activity的xml的加載
-
初始化:
Activity.setContentView -->PhoneWindow.setContentView -->PhoneWindow.installDecor() -->創(chuàng)建DecorView對象和mContentParent對象 -->注意mContentParent是DecorView加載的xml里面的一個fragment
-
填充Layout:
如果設(shè)置了FEATURE_CONTENT_TRANSITIONS,就會創(chuàng)建Scene完成轉(zhuǎn)場動畫悬荣。否則使用布局填充器將布局文件填充至mContentParent菠秒。到此為止,Activity的布局文件已經(jīng)添加到DecorView里面了
Activity的啟動和Window的添加
Activity的啟動氯迂,最終會由ActivityThread中的handleLaunchActivity()來完成整個啟動過程践叠,在這個方法中會通過performLaunchActivity()方法創(chuàng)建Activity,performLaunchActivity()內(nèi)部通過類加載器創(chuàng)建Activity的實(shí)例對象嚼蚀,并調(diào)用其attach()方法為其關(guān)聯(lián)運(yùn)行過程中所依賴的一系列上下文環(huán)境變量以及創(chuàng)建與綁定窗口
在Activity的attach()方法里禁灼,系統(tǒng)會創(chuàng)建Activity所屬的Window對象并為其設(shè)置回調(diào)接口,Window對象會綁定WindowManager轿曙,由于Activity實(shí)現(xiàn)了Window的Callback接口弄捕,因此當(dāng)Window接收到外界的狀態(tài)改變時就會回調(diào)Activity的方法
類似于PhoneWindow和Window的關(guān)系,WindowManager是一個接口导帝,具體的實(shí)現(xiàn)是WindowManagerImpl
-
經(jīng)過了上面幾個過程守谓,Window和DecorView已經(jīng)被創(chuàng)建并初始化完畢,Activity的布局文件也成功添加到了DecorView的mContentParent中您单,但這個時候的DecorView還沒有被WindowManager正式添加到Window中斋荞,
Window可以成功使用有2個標(biāo)志:
- View繪制完畢,可以呈現(xiàn)給用戶
- View可以接收外界信息(觸摸事件等
-
handleLaunchActivity()方法中handleResumeActivity()睹限,首先配置ActivityClientRecord譬猫,之后將DecorView設(shè)置為INVISIBLE讯檐,因?yàn)閂iew并未繪制完成羡疗,當(dāng)前的DecorView只是一個有結(jié)構(gòu)的空殼,然后通過WindowManagerImpl將DecorView正式的添加到窗口上别洪,
這一步非常非常重要叨恨,因?yàn)樗?個比較重要和常見的過程:Window的添加過程和View的繪制流程。wm.addView(decor, l) -->mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow) --> ViewRootImpl.setView(view, wparams, panelParentView)
ViewRootImpl的setView()方法中的requestLayout()完成View的繪制流程挖垛,并且通過WindowSession將View和InputChannel添加到WmS中痒钝,從而將View添加到Window上并且接收觸摸事件秉颗。
添加窗口
添加窗口是通過WindowManagerGlobal的addView方法操作的,這里有三個必要參數(shù)送矩。view蚕甥,params,display栋荸。
display : 表示要輸出的顯示設(shè)備菇怀。
view : 表示要顯示的View,一般是對該view的上下文進(jìn)行操作晌块。(view.getContext())
-
params : 類型為WindowManager.LayoutParams爱沟,即表示該View要展示在窗口上的布局參數(shù)。其中參數(shù):
1.flags
該參數(shù)表示W(wǎng)indow的屬性匆背,它有很多選項(xiàng)呼伸,通過這些選項(xiàng)可以控制Window的顯示特性,這里主要介紹幾個比較常用的選項(xiàng)钝尸。FLAG_NOT_FOCUSABLE
FLAG_NOT_TOUCH_MODAL
FLAG_SHOW_WHEN_LOCKED
2.type
Type參數(shù)表示W(wǎng)indow的類型括享,Window有三種類型,分別是應(yīng)用Window珍促、子Window奶浦、系統(tǒng)Window。應(yīng)用類Window對應(yīng)著一個Activity踢星。子Window不能單獨(dú)存在澳叉,它需要附屬在特定的父Window之中,比如常見的PopupWindow就是一個子Window沐悦。有些系統(tǒng)Window是需要聲明權(quán)限才能創(chuàng)建的Window成洗,比如Toast和系統(tǒng)狀態(tài)欄這些都是系統(tǒng)Window。在三類Window中藏否,應(yīng)用Window的層級范圍是199瓶殃。子Window的層級范圍是10001999,系統(tǒng)Window的層級范圍是2000~2999副签,這些層級范圍對應(yīng)著WindowManager.LayoutParams的type參數(shù)遥椿。如果想要Window位于所有Window的最頂層,那么采用較大的層級即可淆储。另外有些系統(tǒng)層級的使用是需要聲明權(quán)限的冠场。