Activity Window View 三者之間的關係

問題引入

  • 代碼寫久了發現有些問題,到底那些view時怎麼顯示在屏幕上的,怎麼顯示在window上的,還有我們剛開始學習android時候,每次新建一個Activity,在onCreate方法中都會使用setContentView這個方法傳遞一個佈局,它又是怎麼顯示到屏幕上的呢?

首先Actiivity就是創建了一個Window,Activity實際就是Context的一個子類,Context是一個抽象類。。(Activity在創建的時候就創建了一個Window,同時也創建一個decorview)

  • DecorView是什麼?

DecorView是Activity中的頂級View,內部包含標題欄和內部欄

在第二部分在事件傳遞初始時候,單擊事件從Activity傳遞到Window再到傳遞給DecorView,再由DecorView傳遞給我們的View,我們來學習一下它們三者之間的關係。

  • 按鈕是怎麼顯示在Activity上的內,是怎麼繪製在手機屏幕的呢?

答案:通過Window這個類,在Activity創建的時候會創建一個Window,Window通過viewroot將decorview和view添加在window上。

我麼在創建Activity的時候,系統會自動幫我們創建一個decorview,decorview是依賴viewroot將自己添加到window上。

Window的基本介紹

Android所有的視圖都是通過Window來呈現的,不管是Activity,Dialog還是Toast,它們的視圖都是附加在Window上的,因此Window是View的實際操控者。

如何使用WindowManager添加一個Window,過程代碼是什麼樣的。

注意這其中有一個WindowManager.LayoutParams(),()裏面的參數包括一個flag和一個type,flag(flag參數表示window的屬性),分那些種類型,代表什麼含義,type分那幾種(type參數表示window的類型),表示什麼含義。

Window的創建過程

前言

Window一共分爲幾種基本類型:應用Window(Activity),子Window(Dialog),系統Window(toast)
有視圖的地方就有Window,因此Activity Dialog Toast等視圖都應對應着一個Window,有視圖的地方就有Window,PopUpWindow也應該對應着Window。

Window的創建過程,Window事抽象類,它的實現類是PhoneWindow。創建一個Window是一個很簡單的事,只需要通過WindowManager來完成,其實Activity的設置視圖方法setContentView在底層也是通過Window來完成的,查看源碼發現調用的事phoneWindow的setContentView

分上面三種Window分別講解Window的創建過程

Activity的Window創建過程

第一步:在創建Activity實例的時候,系統就會創建Activity所屬的Window對象,併爲Window
對象設置回調Callback接口(留下懸念注意這個接口什麼時候調用哈),創建的方法是PolicyManager的makeNewWindow 策略模式創建出來的Window

第二步:Window創建完成後,分析Activity的視圖是怎麼附屬到Window上的。看代碼,這時候的代碼只有一處調用setContentView,查看setContentView,發現裏面是調用getWindow.setContentView,接下來查看PhoneWindow的setContentView方法

第三步:分析PhoneWindow的setContentView,內部首先判斷是否有DecorView,如果沒有DecorView,則去創建DecorView,DecorView包括標題欄和內部欄。

第四步:有了DecorView,將View(也就是將Activity中的視圖)添加到DecorView的mContentParent中。到此爲止,Activity的佈局已經添加到了DecorView中了

第五步:第一步中Activity爲Window設置了回調函數,是時候調用這些回調函數了,一旦確定了佈局文件已經添加到了DecorView的mContentParent中,就需要通知Activity做一些處理。

第六步:條件都具備後,佈局文件已經成功添加到了DecorView的mContentParent中,是時候添加到Window中了,在ActivityThread的handleResumeActivity方法中,會調用Activity的onResume方法,接着會調用Activity的makeVisable(),在這個方法中DecorView真正的完成了添加和顯示兩個過程,到這裏Activity視圖才被用戶看到。

++(在這裏也明白了Activity的生命週期,在onResume執行後才真的能被看到)++

Dialog的Window創建過程

Dialog的Window創建過程基本與Activity相同

簡單說一下:

第一步:創建Window,不過是在Dialog的函數中完成的,實際方法與Activity中的相同,Policy.makeNewWindow

第二步:仍然是使用setContentView初始化DevorView,然後將佈局文件也就是Dialog的視圖添加到DetorView中

第三步:將DetorView添加到Window中顯示,dialog調用show方法的時候,會通過WindowManager.addView添加到Window中

++(在這裏我也終於想明白了爲什麼自定義Dialog的時候調用一個setContentView,而在自定義RowView的時候使用 LayoutInflater.from(mContext).inflate就可以)++

注意點:普通的dialog,創建的時候,必須採用Activity的Context,如果採用Application的Context會報錯,也不是沒有解決辦法,改變Window的Type類型,爲系統類型,然後不要忘了添加權限

dialog.getWindow().setType(LayoutParams.TYPE_SYSTEM_ERROR);
權限文件中添加SYSTEM_ALERT_WINDOW
(上面事什麼原因有沒有考慮過,爲什麼Dialog使用Application的Context會報錯,報錯顯示缺少token,token一般只有在Activity中有,無法獲取到token,而系統Window不需要token,也能正常顯示視圖彈出框,就有了上面的解決辦法)

Toast的Window創建過程

PopWindow的Window創建過程

Window的三種類型上面已經提到過應用Window(Activity),子Window(Dialog)系統Window(Toast),但是對於PopUpWindow,菜單也同樣是視圖,有視圖的地方就有Window,也同樣會創建Window

Activity,Window,View三者功能總結:

  • Activity就是控制單元(控制Window,同時也依賴Window)

  • Window是承載模型(承載view和decorview)

  • view是顯示視圖(通過viewroot顯示到window上,decorview是依賴viewroot顯示到window上,創建activity的時候就創建了decorview,setContentView將我們自己定義的view建立到decorview上)

聯想:

開發商賣房子的裝修風格,符合可以用,可以改,不符合都不用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章