理清Activity、View及Window之間關係
View
、Window
以及Activity
主要是用於顯示並與使用者互動的。這讓我們在初學的時候很容易弄混,而且無法理解他們區別以及聯絡。本文是筆者查閱相關資料後,結合自己的理解寫出來。希望能幫你梳理清楚他們各自的工作職責,以及是因為什麼需求導致了它們的出現。
1 View
從我之前寫的【從Android程式碼中來記憶23種設計模式 】這篇文章可知,View
(包括ViewGroup
)使用的是組合模式,即:
將
View
組成成樹形結構,以表示“部分-整體”的層次結構,使得使用者對單個物件和組合物件的使用具有一致性。
我們知道,View
主要是用於繪製我們想要的結果,是一個最基本的UI
元件。
2 Window
2.1 Window的基本理解
簡單地說,Window
表示一個視窗,一般來說,Window
大小取值為螢幕大小。但是這不是絕對的,如對話方塊、Toast
等就不是整個螢幕大小。你可以指定Window的大小。Window
包含一個View tree
和視窗的layout
引數。
感覺Window
的理解比較抽象,我個人的理解是,Window
相當於一個容器,裡面“盛放”著很多View
,這些View
是以樹狀結構組織起來的。
如果你還是無法理解的話,你就把Window
當成是顯示器,顯示器有大有小(對應Window
有大有小),View
是顯示器裡面具體顯示的內容。
2.2 Window物件有存在的必要嗎?
我個人長期有個困惑:Window
能做的事情,View
物件基本都能做:像什麼觸控事件啊、顯示的座標及大小啊、管理各個子View
啊等等。View
已經這麼強大了,為什麼還多此一舉,加個Window
物件。可能有人會說因為WindowManager
管理的就是Window
物件呀,那我想問,既然這樣,Android
系統直接讓WindowManager
去管理View
不就好了?讓View
接替Window
的工作,把Window
所做的事情都封裝到View
裡面不好嘛?(至少免去了我們去理解抽象的Window
,,,,O__O “…)。或許又有人說,View負責繪製顯示內容,Window負責管理View,各自的工作職責不同。可是我想說,Window所做的大部分工作,View裡面都有同樣(或類似)的處理。這依然無法說服我!
關於Window
存在的必要,我查了國內外各種資料,最後有了我個人的理解(如果有錯也歡迎評論糾正~)。在後面小節裡面,我會結合我個人的理解來解釋。在解釋之前,我們需要了解Window
繪製過程。
2.3 Window繪製過程
在理解Window
繪製過程之前,首先,我們需要知道Surface
,在Window
中持有一個Surface
,那麼什麼是Surface
呢?
Surface
其實就是一個持有畫素點矩陣的物件,這個畫素點矩陣是組成顯示在螢幕的影象的一部分。我們看到顯示的每個Window
(包括對話方塊、全屏的Activity
、狀態列等)都有他自己繪製的Surface
。而最終的顯示可能存在Window
之間遮擋的問題,此時就是通過Surface Flinger
物件渲染最終的顯示,使他們以正確的Z-order
顯示出來。一般Surface
擁有一個或多個快取(一般2個),通過雙快取來重新整理,這樣就可以一邊繪製一邊加新快取。
WindowManager
為每個Window
建立Surface
物件,然後應用就可以通過這個Surface
來繪製任何它想要繪製的東西。而對於WindowManager
來說,這只不過是一塊矩形區域而已。
前面我們說過,View
是Window
裡面用於互動的UI
元素。Window
只attach
一個View Tree
,當Window
需要重繪(如,當View
呼叫invalidate
)時,最終轉為Window
的Surface
,Surface
被鎖住(locked
)並返回Canvas
物件,此時View
拿到Canvas
物件來繪製自己。當所有View
繪製完成後,Surface
解鎖(unlock
),並且post
到繪製快取用於繪製,通過Surface Flinger
來組織各個Window
,顯示最終的整個螢幕。
2.4 關於Window物件存在的必要
以下是我個人理解!
現在我們知道了Window
繪製過程,其實,站在系統的角度來考慮,一個Window
物件代表一塊顯示區域,系統不關心Window
裡面具體的繪製內容,也不管你Window
怎麼去繪製,反正只給你提供可以在這塊區域上繪製圖形的Surface
物件,你Window
物件怎麼畫是你的事情!
換句話說,站在系統的角度上看,系統是“不知道”有View
物件這個說法的!作為系統,我有自己的驕傲,不去管你Window
如何搬磚、如何砌牆,只給你地皮。而這時,Window
為了繪製出使用者想要的元件(按鈕、文字、輸入框等等),系統又不給我!沒事,那我自己定義,於是就定義了View
機制,給每個View
提供Canvas
,讓不同的View
自己繪製具有自己特色的元件。同時,為了更好的管理View
,通過定義ViewGroup
,等等。
相信看到這,你就知道為什麼需要Window
了,當然了,本文並不是去糾纏要不要Window
物件這個問題。而是通過這個問題,讓我們理清View
與Window
的區別。這才是重點!到這裡,如果理由說服不了你,那你就不要去糾纏了。至少,你已經理清了View
與Window
之間的關係了,這就夠了!
3 Activity
3.1 Activity基本理解
對於開發人員來說,一個Activity
就“相當於”一個介面(通過setContentView
指定具體的View
)。我們可以直接在Activity裡處理事件,如onKeyEvent
,onTouchEvent
等。 並可以通過Activity
維護應用程式的生命週期。
3.2 Activity有存在的必要嗎?
同樣,我們還是以是否存在這個問題為切入點,去理清
Activity
與Window
關係。
前面我們知道,Window
已經是系統管理的視窗介面。那麼為什麼還需要Activity
呢?我們把Activity
所做的事情,全部封裝到Window
不就好了?
其實,本質上講,我們要顯示一個窗口出來,的確可以不需要Activity
。懸浮視窗中不就是沒有使用Activity
來顯示一個懸浮窗嗎?既然如此,Window
(以及View
)能處理點選事件以及封裝各種邏輯,那為啥還需要Activity呢?
個人理解:
Android
中的應用中,裡面對各個視窗的管理相當複雜(任務棧、狀態等等),Android
系統當然可以不用Activity
,讓使用者自己直接操作Window
來開發自己的應用。但是如果讓使用者自己去管理這些Window
,先不說工作量,光讓使用者自己去實現任務棧這點,有幾個人能寫的出來。為了讓大家能簡單、快速的開發應用,Android
通過定義Activity,讓Activity
幫我們管理好,我們只需簡單的去重寫幾個回撥函式,無需直接與Window
物件接觸。各種事件也只需重寫Activity
裡面的回撥即可。無需關注其他細節,預設都幫我們寫好了,針對需要定製的部分我們重寫(設計模式為:模板方法模式)。