1.Window與WindowManager
Window是一個抽象類拌阴,==它的具體實現(xiàn)是PhoneWindow==,==Window創(chuàng)建時通過WindowManager完成==奶镶。
WindowManager與WindowManagerService交互是一個IPC過程迟赃。
Flags--Window屬性
- FLAG_NOT_FOCUSABLE--表示當(dāng)前Window不需要焦點(diǎn),也不需要接收事件厂镇,事件將傳遞給下層具有焦點(diǎn)的window纤壁。
- FLAG_NOT_TOUCH_MODAL--系統(tǒng)會將window區(qū)域以外的單擊事件傳遞給底層的window,當(dāng)前window區(qū)域以內(nèi)的單擊事件則自己處理,這個標(biāo)記很重要,一般都要開啟嗤无。
- FLAG_SHOW_WHEN_LOCKED--可以讓window顯示在鎖屏的界面上翩概。
Type--Window類型
- 應(yīng)用window--對應(yīng)著一個Activity
- 子window -- 需要附屬在特定的父window之中劳秋,Dialog
- 系統(tǒng)window--需要聲明權(quán)限才能創(chuàng)建的Window,Toast、系統(tǒng)狀態(tài)欄
每個window對應(yīng)z-ordered,==層級大的會覆蓋在層級小的window上面==雨席。其中應(yīng)用Window的層級范圍1-99,子Window的層級范圍是1000-1999吠式,系統(tǒng)Window的層級范圍是2000-2999陡厘。
Window和WM、WMS
Window是一個抽象概念特占,==每個Window都對應(yīng)著一個View和一個ViewRootImpl糙置,Window和View通過ViewRootImpl來建立聯(lián)系==,因此==Window并不是實際存在的摩钙,它是以View的形式存在的==罢低。
PhoneWindow是唯一實現(xiàn)Window的類,它將DecorView設(shè)為根View胖笛,每個Activity都有一個PhoneWindow對象网持。==PhoneWindow是Activity和View系統(tǒng)交互的橋梁==。
在setContentView中长踊,其實是通過Activity中間代理了一層功舀,最終還是會調(diào)用到PhoneWindow。mContentParent為空時表示當(dāng)?shù)谝淮螘r身弊,當(dāng)前內(nèi)容未放置到窗口辟汰,便調(diào)用了installDecor方法。installDecore方法就是用來添加DecorView根View的阱佛。mLayoutInflater.inflate(layoutResID, mContentParent);的將layoutResID關(guān)聯(lián)的View添加到DecorView中去帖汞。最后還有就是通過onContentChanged方法回調(diào)通知Activity。
==WindowManager是外界訪問Window的入口==凑术,它是一個接口翩蘸,它繼承于ViewManager。==負(fù)責(zé)Window的管理工作淮逊,實現(xiàn)類是WindowManagerImpl催首,而添加、更新泄鹏、刪除這三個對View的操作交由WindowManagerGlobal來處理==郎任。
ViewManager一個接口,它是用來添加和移除activity中View的接口备籽,它定義了一組操作View的方法:add舶治、update、remove车猬。
WindowManagerImpl是WindowManager的實現(xiàn)類霉猛,實質(zhì)上它沒干什么事情,可以理解成是一個代理诈唬,它有一個WindowManagerGlobal的單例對象韩脏,所有事情都是由WindowManagerGlobal來處理的,也是真正處理View的添加铸磅、更新赡矢、刪除的地方。
WindowManagerService
WindowManagerService是一個系統(tǒng)服務(wù)阅仔,運(yùn)行在單獨(dú)的線程中吹散,管理系統(tǒng)中所有的Window,注意是所有八酒。在Window的添加空民、更新和刪除過程中,其實就是WindowManager和WindowManagerService的IPC調(diào)用中完成。
Window的添加過程界轩、刪除過程画饥、更新過程
在addview過程中,調(diào)用了ViewRootImpl的setView方法浊猾,View的繪制就是由它來完成的抖甘。
mWindowSession是一個IWindowSession接口,它是一個Binder對象葫慎,真正的實現(xiàn)類是Session衔彻,這也就是之前提到的IPC過程,然后在 Session 內(nèi)部會通過 WindowManagerService的addWindow 來實現(xiàn) Window 的添加偷办。整個過程艰额, Window 的添加請求移交給 WindowManagerService 去處理了 。
Activity 的 Window 創(chuàng)建過程
在了解了 Window 的概念及意義后椒涯,我們自然就清楚 Activity 的 Window 創(chuàng)建時機(jī)柄沮,Window 本質(zhì)就是一塊顯示區(qū)域,==所以關(guān)于 Activity 的 Window 創(chuàng)建應(yīng)該發(fā)生在 Activity 的啟動過程==逐工,Activity 的啟動過程很復(fù)雜铡溪,最終會由 ActivityThread 中的 performLaunchActivity() 來完成整個啟動過程,在這個方法內(nèi)部會通過類加載器創(chuàng)建 Activity 的實例對象泪喊,并調(diào)用其 attach 方法為其關(guān)聯(lián)運(yùn)行過程中所依賴的一系列上下文環(huán)境變量棕硫。
==Activity 的 Window 創(chuàng)建就發(fā)生在 attach 方法里==,系統(tǒng)會創(chuàng)建 Activity 所屬的 Window 對象并為其設(shè)置回調(diào)接口袒啼,代碼如下:
mWindow = PolicyManager.makeNewWindow(this)哈扮;
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
...
可以看到,== Window 對象的創(chuàng)建是通過 PolicyManager 的 makeNewWindow 方法實現(xiàn)的==蚓再,由于 Activity 實現(xiàn)了 Window 的 Callback 接口滑肉,因此當(dāng) Window 接受到外界的狀態(tài)改變時就會回調(diào) Activity 的方法。Callback 接口中的方法很多摘仅,有幾個是我們非常熟悉的靶庙,如 onAttachedToWindow、onDetachedFromWindow娃属、dispatchTouchEvent 等等六荒。
再回到 Window 的創(chuàng)建,可以看到 ==Activity 的 Window 是通過 PolicyManager 的一個工廠方法來創(chuàng)建的矾端,但是在 PolicyManager 的實際調(diào)用中掏击,PolicyManager 的真正實現(xiàn)是 Policy 類==,Policy 類中的 makeNewWindow 方法的實現(xiàn)如下:
public Window makeNewWindow(Context context){
return new PhoneWindow(context);
}
可以看出秩铆,Window 的具體實現(xiàn)類的確是 PhoneWindow砚亭。到這里 Window 已經(jīng)創(chuàng)建完成了,下面分析 ==Activity 的視圖是怎么附屬到 Window 上的==,而 Activity 的視圖由 setContentView 提供捅膘,所以從 setContentView 入手添祸,它的源碼如下:
public void setContentView(int layoutResID){
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
可以看到,Activity 將具體實現(xiàn)交給了 Window篓跛,而 Window 的具體實現(xiàn)是 PhoneWindow膝捞,所以只需要看 PhoneWindow 的相關(guān)邏輯即可坦刀,它的處理步驟如下:
(1)愧沟、如果沒有 DecorView 就創(chuàng)建一個
DecorView 是 Activity 中的頂級 View,是一個 FrameLayout鲤遥,一般來說它的內(nèi)部包含標(biāo)題欄和內(nèi)容欄沐寺,但是這個會隨著主題的變化而改變,不管怎么樣盖奈,內(nèi)容欄是一定存在的混坞,并且有固定的 id:”android.R.id.content”,在 PhoneWindow 中钢坦,通過 generateDecor 方法創(chuàng)建 DecorView究孕,通過 generateLayout 初始化主題有關(guān)布局。
(2)爹凹、將 View 添加到 DecorView 的 mContentParent 中
這一步較為簡單厨诸,直接將 Activity 的視圖添加到 DecorView 的 mContentParent 中即可,由此可以理解 Activity 的 setContentView 這個方法的來歷了禾酱,為什么不叫 setView 呢微酬?因為 Activity 的布局文件只是被添加到 DecorView 的 mContentParent 中,因此叫 setContentView 更加具體準(zhǔn)確颤陶。
(3)颗管、回調(diào) Activity 的 onContentChanged 方法通知 Activity 視圖已經(jīng)發(fā)生改變
前面分析到 Activity 實現(xiàn)了 Window 的 Callback 接口,這里當(dāng) Activity 的視圖已經(jīng)被添加到 DecorView 的 mContentParent 中了滓走,需要通知 Activity垦江,使其方便做相關(guān)的處理。
==經(jīng)過上面的三個步驟搅方,DecorView 已經(jīng)被創(chuàng)建并初始化完畢比吭,Activity 的布局文件也已經(jīng)成功添加到了 DecorView 的 mContentParent 中==,但是這個時候 DecorView 還沒有被 WindowManager 正式添加到 Window 中腰懂。在 ActivityThread 的 handleResumeActivity 方法中梗逮,首先會調(diào)用 Acitivy 的 onResume 方法,接著會調(diào)用 Acitivy 的 makeVisible() 方法绣溜,正是==在 makeVisible 方法中慷彤,DecorView 才真正的完成了顯示過程==,到這里 Activity 的視圖才能被用戶看到,如下:
void makeVisible(){
if(!mWindowAdded){
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}