在開發中我們會遇到各種各樣的非常奇怪的問題,有些問題是百思不得騎姐。其實這些問題大都是因為我們不瞭解安卓內部執行原理,知其所以然才是我們的目的。—前言
任何控制類程式都有一個入口,安卓應用程式肯定也是有滴。
Android framework包含三個小夥伴:服務端、客戶端、linux驅動。
服務端
服務端主要包含兩個狠重要的類:WindowManagerService(WMS)和ActivityManagerService(AMS)
客戶端
客戶端包含以下類:
ActivityThread:是安卓應用程式的主執行緒類,這個小夥伴所在的執行緒就是UI執行緒或者稱為主執行緒。
Activity:ActivityThread會根據使用者的操作選擇讓哪個Activity物件上它的船。
PhoneWindow:富二代,繼承於牛氣的Window類,自己屋裡住著一個DecorView物件,像它老爸喜歡制定規則提供了一些通用視窗操作API。
Window:富一代,長得比較抽象,喜歡制定規則提供了一些通用的視窗操作API。它不喜歡被人管所以呢,注意:WindowManagerService管理的視窗不是Window類,其實是View和ViewGroup。
DecorView:很能幹的傢伙,家產來自FrameLayout,比較注重外在喜歡打扮,DecorView是對FrameLayout進行了一些修飾,從名字就可以看出來。
ViewRoot:小管家繼承於Handler,主要作用是把WMS的IPC呼叫轉換為本地的一個非同步呼叫。
W類:ViewRoot小助手,繼承於binder,是ViewRoot內部類。主要幫助ViewRoot實現把WMS的IPC呼叫轉換為本地的一個非同步呼叫。
WindowManager:客戶端如果想建立一個視窗得先告訴WindowManager一聲,然後它再和WindowManagerService交流一下看看能不能建立,客戶端不能直接和WMS互動。
Linux驅動
Linux驅動和Framework相關的主要是兩個部分:畫家SurfaceFlingger和快遞員Binder。
每一個視窗都對應一個畫Surface,SF主要是把各個Surface顯示到同一螢幕上。Binder是提供跨程式的訊息傳遞。
從apk程式的執行過程去看看上面各個元件在啥時候幹啥活的
ActivityThread從main()函式中就開始動起來,然後呼叫prepareMainLooper()為UI執行緒建立一個訊息快遞通道即MessageQueue。
接著建立ActivityThread物件,建立過程會建立一個訊息裝卸工Handler物件和一個快遞員Binder物件,其中Binder負責接收遠端Ams的IPC呼叫,接收到呼叫後讓Handler把訊息裝到訊息快遞佇列,UI執行緒很忙的都是非同步的從訊息快遞佇列中取出訊息並執行相應操作,比如 start、stop、pause。
然後UI執行緒讓佇列呼叫Looper.loop()方法進入訊息迴圈體,進入後就會不斷地從訊息佇列中讀取並處理訊息。
當ActivityThread接收到Ams傳送start某個Activity的快遞後就會建立指定的Activity物件。Activity會先按窗戶再去按玻璃和貼窗花,所以先建立PhoneWindow->DecorView->建立相應的View或ViewGroup。建立完成後就可以讓大家欣賞了,呼叫WindowManager把介面顯示到螢幕上,然後建立ViewRoot,然後呼叫Wms提供的遠端介面新增一個視窗並顯示到螢幕上。
接下來就是使用者的操作,事件執行緒不斷的把訊息快遞發到事件佇列中去,然後事件分發執行緒祕書逐個取出訊息,然後呼叫Wms中的相應函式處理該訊息。
很多執行緒是不是很暈?
安卓程式中都有哪些執行緒?
客戶端小夥伴至少包含三個執行緒小弟,Activity啟動後會建立一個ViewRoot.W物件,同時ActivityThread會建立一個ApplicationThread物件,這兩個物件繼承訊息總管Binder,每個Binder對應一個執行緒,負責接收Linux Binder驅動傳送的IPC呼叫。還有一個是UI執行緒唄。
UI執行緒是什麼?
一直在傾聽使用者的心聲,所有的處理使用者訊息,以及繪製頁面的工作都在該執行緒中完成。
自定義的執行緒和UI執行緒有什麼區別?
UI執行緒是從ActivityThread執行的,在該類的main()方法中已經使用了Looper.prepareMainLooper()為該執行緒新增了Looper物件,已經為該執行緒建立了訊息佇列,是自帶祕書光環的。因此,我們才可以在Activity中去定義Handler物件,因為建立Handler物件時其執行緒必須已經建立了訊息佇列,裝卸工得配運輸帶要不然沒法幹活。而普通的Thread則沒有預設建立訊息佇列,所以不能直接在Thread中直接定義Handler,這個就是我們不懂程式執行原理導致的困惑。
轉載註明出處,如有問題請留言。
備註:以上部分思想來自於《Android核心剖析》