理解Android Window

一、Window和WindowManager

Android中所有視圖都是通過Window來呈現(xiàn)的窖逗,Activity、Dialog餐蔬、Toast的視圖實(shí)際上都是附加在Window上的碎紊,因此Window實(shí)際上是View的直接管理者。

Window有幾種屬性樊诺,使用Flags參數(shù)表示仗考,例如FLAG_NOT_FOCUSABLE表示不需要獲取焦點(diǎn),F(xiàn)LAG_NOT_TOUCH_MODAL表示W(wǎng)indow區(qū)域以外的點(diǎn)擊事件傳遞給底層的Window词爬,當(dāng)前區(qū)域事件則自己處理(一般都要開啟這個(gè)Flag)秃嗜,F(xiàn)LAG_SHOW_WHEN_LOCKED可鎖屏顯示。

Window是分層的顿膨,層級(jí)大的會(huì)覆蓋層級(jí)小的锅锨,應(yīng)用Window < 子Window < 系統(tǒng)Window層級(jí)。

WindowManager是外界訪問Window的入口恋沃,Window的具體實(shí)現(xiàn)是位于WindowManagerService中必搞,WindowManager和WindowManagerService交互是IPC過程。

二囊咏、Window的內(nèi)部機(jī)制

1. Window和View及ViewRoot的關(guān)系

Window 是一個(gè)抽象的概念恕洲,每一個(gè)Window都對(duì)應(yīng)一個(gè)View和一個(gè)ViewRootImpl,Window和View通過ViewRootImpl來建立聯(lián)系梅割。

在Window添加View的過程中霜第,為其內(nèi)部創(chuàng)建了一個(gè)ViewRootImpl對(duì)象,負(fù)責(zé)繪制顯示各個(gè)子View户辞,而ViewRootImpl中調(diào)用的setView()方法會(huì)輾轉(zhuǎn)調(diào)用performTraversals()方法從而實(shí)現(xiàn)View的一系列繪制流程泌类。

操作Window的三個(gè)方法:

public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);

創(chuàng)建并顯示W(wǎng)indow只需向其添加View,刪除Window只需刪除里面的View即可咆课。

2. Window的添加

WindowManager的addView()全部委托給了WindowManagerGlobal來實(shí)現(xiàn)末誓,做了如下工作:

  1. 檢測(cè)參數(shù)是否合法扯俱,對(duì)于子Window調(diào)整布局參數(shù)。
  2. 創(chuàng)建ViewRootImpl并將View添加到列表中喇澡。
  3. 通過ViewRootImpl更新界面迅栅,其setView()調(diào)用performTravelsals()會(huì)繪制整個(gè)View,接著通過WindowSession與WindowManagerService進(jìn)行IPC調(diào)用來實(shí)現(xiàn)Window的添加晴玖。

3. Window的刪除

全部委托給了WindowManagerGlobal來實(shí)現(xiàn)读存。
1.查找待刪除的View索引
2.通過ViewRootImpl完成接下來的刪除操作,對(duì)于異步刪除的情況呕屎,ViewRootImpl發(fā)送一個(gè)MSG_DIE消息让簿,由ViewRootImpl的Handler處理此消息來刪除。
3.刪除主要做垃圾回收相關(guān)秀睛,通過Session來IPC調(diào)用WindowManagerService的刪除方法移除Window尔当,最后由WindowManagerGlobal刷新數(shù)據(jù)。

4. Window更新

全部委托給了WindowManagerGlobal來實(shí)現(xiàn)蹂安。

首先更新View的LayoutParams并替換老的LayoutParams椭迎,再更新ViewRootImpl的LayoutParams,此時(shí)會(huì)通過scheduleTraversals()對(duì)View重新布局田盈。最后通過WindowSession的IPC更新Window的視圖畜号。

三、Window的創(chuàng)建

1. Activity的Window創(chuàng)建及與View的聯(lián)系建立

attach()

在創(chuàng)建Activity的performLaunchActivity()方法中會(huì)調(diào)用attach()方法創(chuàng)建PhoneWindow并為其關(guān)聯(lián)一系列上下文環(huán)境變量允瞧。

setContentView()

接下來是Window如何添加View简软。是從Activity的setContentView()開始的:

    public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
    }

實(shí)際是調(diào)用了Window的setContentView(),他分為下面的步驟:

  1. 如果沒有DecorView就創(chuàng)建它述暂,其中根據(jù)Theme的不同加載不同的布局格式痹升。
  2. 將Activity的布局的View添加到DecorView的mContentParent中,這里mContentParent指的就是@android:id/content所對(duì)應(yīng)的FrameLayout贸典,如下圖视卢,也就是圖中ContentViews那部分。
DecorView廊驼,WindowManager据过,Activity關(guān)系

3.回調(diào)Activity的OnContentChanged()方法。

onResume()

真正想讓W(xué)indow中的視圖被看到妒挎,是在Activity的onResume()方法被調(diào)用之后才實(shí)現(xiàn)的绳锅,此時(shí)會(huì)調(diào)用WindowManager的addView()方法添加DecorView在Window中,再調(diào)用Activity的makeVisiable()方法使得View可見酝掩。

void makeVisible() {
   if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());//將DecorView添加到WindowManager
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);//DecorView可見
    }

注:ViewRootImpl作為一個(gè)連接器鳞芙,當(dāng)用戶點(diǎn)擊屏幕時(shí),觸摸行為通過硬件傳遞來捕獲,然后交給ViewRootImpl原朝,接著將事件傳遞給DecorView驯嘱,再交給PhoneWindow,PhoneWindow再交給Activity喳坠,然后View事件分發(fā)鞠评。

2. Dialog的Window創(chuàng)建

和Activity類似,也是需要?jiǎng)?chuàng)建DecorView壕鹉,特殊之處在于需要采用Activity的Context剃幌,因?yàn)镈ialog創(chuàng)建需要應(yīng)用token,這個(gè)token只有Activity有晾浴,所以不能用Application的token负乡。一種解決的方法是將Window設(shè)置為系統(tǒng)層級(jí),就不需要token了脊凰。

3. Toast的Window創(chuàng)建

Toast屬于系統(tǒng)Window抖棘,比較復(fù)雜。

首先是Toast通過IPC遠(yuǎn)程調(diào)用NotificationManagerService的方法將請(qǐng)求添加到ToastQueue隊(duì)列中(最多容納50個(gè)Toast)笙各,然后NotificationManagerService再通過IPC遠(yuǎn)程調(diào)用Toast的TN對(duì)象的Binder钉答,實(shí)現(xiàn)視圖在Window中的添加和刪除。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末杈抢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子仑性,更是在濱河造成了極大的恐慌惶楼,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诊杆,死亡現(xiàn)場(chǎng)離奇詭異歼捐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)晨汹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門豹储,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人淘这,你說我怎么就攤上這事剥扣。” “怎么了铝穷?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵钠怯,是天一觀的道長。 經(jīng)常有香客問我曙聂,道長晦炊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮断国,結(jié)果婚禮上贤姆,老公的妹妹穿的比我還像新娘。我一直安慰自己稳衬,他們只是感情好霞捡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著宋彼,像睡著了一般弄砍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上输涕,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天音婶,我揣著相機(jī)與錄音,去河邊找鬼莱坎。 笑死衣式,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的檐什。 我是一名探鬼主播碴卧,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼乃正!你這毒婦竟也來了住册?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤瓮具,失蹤者是張志新(化名)和其女友劉穎荧飞,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體名党,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡叹阔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了传睹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片耳幢。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖欧啤,靈堂內(nèi)的尸體忽然破棺而出睛藻,到底是詐尸還是另有隱情,我是刑警寧澤堂油,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布修档,位于F島的核電站,受9級(jí)特大地震影響府框,放射性物質(zhì)發(fā)生泄漏吱窝。R本人自食惡果不足惜讥邻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望院峡。 院中可真熱鬧兴使,春花似錦、人聲如沸照激。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽俩垃。三九已至励幼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間口柳,已是汗流浹背苹粟。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留跃闹,地道東北人嵌削。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像望艺,于是被迫代替她去往敵國和親苛秕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355