Framework定義了客戶端組件和服務器端組件功能及接口,包含3個部分:服務端、客戶端和linux驅動,以下圖所示: linux
Framework中所包含的服務是很是多的,爲了清晰的描述服務端、客戶端和linux驅動三者的關係,咱們只是描述了它們其中的一小部分,這一小部分也是爲後續講解窗口的建立、Activity啓動、繪製、事件分發服務的。程序員
服務端主要包含兩個重要類,分別是WindowManagerService(WMS)和ActivityManagerService(AMS):api
除此以外,在服務端還包括2個信息處理類:服務器
客戶端主要包括如下重要類:框架
ActivityThread類
該類爲應用程序的主線程類,全部的APK程序有且只有一個ActivityThread類,程序的入口爲該類中的static main()函數,ActivityThread所在的線程即爲ui線程或主線程。異步
Activity類
該類爲APK程序的一個最小運行單位,一個apk程序中能夠包含多個activity對象,activityThread主類會根據用戶操做選擇運行哪一個activity對象。函數
PhoneWindow類
該類繼承與Window類,同時phonewindow類內部包含了一個decorView對象,簡而言之,PhoneWindow是把一個FrameLayout進行了必定的包裝,並提供了一組通用的窗口操做接口。oop
Window類
該類是一組通用的窗口window操做api,這裏的窗口僅僅是程序層面上的,wms所管理的窗口並非window類,而是一個view或者viewgroup類,通常就是指DecorView類,即一個D而從容View就是wms全部管理的一個窗口,window是一個abstact類型。ui
DecorView類
該類是一個FrameLayout的子類,而且是PhoneWindow的一個內部類,DecorView就是對普通的FrameLayout進行了必定的修飾,好比添加一個通用的TitleBar,並響應特定的按鈕消息等。spa
ViewRoot類
Wms管理客戶端窗口時,須要通知客戶端進行某種操做,這些都是經過IPC調用完成的,而在客戶端窗口收到IPC調用後,都會把該調用轉換爲本地的一個異步調用,實現方式就是使用handler,ViewRoot就是繼承與handler,其主要做用就是就接手wms的IPC調用轉換爲本地的一個異步調用。
w類
該類繼承於Binder,而且是一個viewRoot的一個內部類。WMS通知客戶端窗口時,是經過IPC調用,也就是調用該Binder類,而後該Binder內部的處理函數通常會給該類所在的ViewRoot類發送一個Handler消息,以便進行異常處理。
windowManager類
客戶端要申請建立一個窗口,而具體建立窗口的任務是有wms完成的,windowManager類就像是一個部門經理,誰有什麼需求就告訴他,由它和wms進行交互,客戶端不能直接和wms進行交互。
Linux驅動和Framework相關的主要包含兩個部分,分別是surfaceFlingger和Binder,每個窗口都對應一個Surface,sf驅動的做用就是把各個surface顯示在同一個屏幕上。
Binder驅動的做用是提供框進程 ipc 的消息傳遞機制。
下圖是一個更加完成的APK程序工做的流圖:
而後建立一個ActivityThread對象,在ActivityThread的初始化代碼中會建立一個H(Handler)對象和一個ApplicationThread(Binder)對象。其中Binder負責接收遠程AmS的IPC調用,接收到調用後,則經過Handler把消息發送到消息隊列,UI主線程會異步地從消息隊列中取出消息並執行相應操做,好比start、stop、pause等。
接着UI主線程調用Looper.loop()方法進入消息循環體,進入後就會不斷地從消息隊列中讀取並處理消息。
當ActivityThread接收到AmS發送start某個Activity後,就會建立指定的Activity對象。Activity又會建立PhoneWindow類→DecorView類→建立相應的View或者ViewGroup。建立完成後,Activity須要把建立好的界面顯示到屏幕上,因而調用WindowManager類,後者因而建立一個ViewRoot對象,該對象實際上建立了ViewRoot類和W類,建立ViewRoot對象後,WindowManager再調用WmS提供的遠程接口完成添加一個窗口並顯示到屏幕上。
接下來,用戶開始在程序界面上操做。KeyQ線程不斷把用戶消息存儲到QueueEvent隊列中,InputDispatcherThread線程逐個取出消息,而後調用WmS中的相應函數處理該消息。當WmS發現該消息屬於客戶端某個窗口時,就會調用相應窗口的W接口。
W類是一個Binder,負責接收Wms的IPC調用,並把調用消息傳遞給ViewRoot,ViewRoot再把消息傳遞給UI線程ActivityThread,ActivityThread解析該消息並作相應的處理。在客戶端程序中,首先處理消息的是DecorView,若是DecorView不想處理某個消息,則能夠將該消息傳遞給其內部包含的子View或ViewGroup,若是尚未處理,則傳遞給PhoneWindow,最後再傳遞給Activity。
在多任務操做系統中,任何程序都運行在線程之中。系統首先會爲客戶端程序分配一個線程,而後該線程從程序的入口處開始執行。那麼,請思考如下問題。
首先,很明確地講,包含有Activity的客戶端程序至少包含三個線程,如圖6-1所示。每一個Binder對象都對應一個線程,Activity啓動後會建立一個ViewRoot.W對象,同時ActivityThread會建立一個ApplicationThread對象,這兩個對象都繼承於Binder,所以會啓動兩個線程,負責接收Linux Binder驅動發送IPC調用。最後一個主要線程也就是程序自己所在的線程,也叫作用戶交互(UI)線程,由於全部的處理用戶消息,以及繪製界面的工做都在該線程中完成。
自定義Thread和UI線程的區別在於,UI線程是從ActivityThread運行的,在該類中的main()方法中,已經使用Looper.prepareMainLooper()爲該線程添加了Looper對象,即已經爲該線程建立了消息隊列(MessageQueue),所以,程序員才能夠在Activity中定義Handler對象(由於聲明Handler對象時,所在的線程必須已經建立了MessageQueue)。而普通的自定義Thread是一個裸線程,所以,不能直接在Thread中定義Handler對象,從使用場景的角度講,即不能直接給Thread對象發消息,可是卻能夠給UI線程發消息。