Android內核之FrameWork學習

前言

任何控制類程序都有一個入口,語言的入口是由處理器內部的復位(Reset)中斷向量表決定的;C程序入口是main()函數;JAVA程序的入口必須是某個類的靜態成員方法main()
Android程序也不例外,那麼Android程序入口在哪裏呢?Android FrameWork都包含哪些系統服務?這些系統服務是如何與AndroidAPK程序配合的?看完這個博客你就會對FrameWork有一定的瞭解了,如果覺得我的博客寫的好的話,記得在博客下方寫個好的評論,歡迎轉載,請標明出處

FrameWork框架

FrameWork定義了客戶端組件和服務端組件功能及接口。
框架中包含三個主要部分,分別服務端,客戶端,和Linux驅動
一,服務端
服務端主要包含兩個重要的類,分別是WindowManagerService(Wms)和ActivityManagerService各窗口的疊放次序,隱藏或者顯示窗口,Ams的作用是管理所有的應用程序的Activity,Wms主要負責窗口的控制,除此之外,在服務端還包括兩個消息處理類,這兩個類分別爲:

  • KeyQ類:該類爲WmS的內部類,繼承於KeyInputQueue類,KeyQ對象一旦創建,就立即開動一個線程,該線程會不斷的讀取用戶的UI操作信息,比如按鍵,觸摸屏,trackball,鼠標等等;
  • InputDispatcherThread類:該類的對象一旦創建,也會立即啓動一個線程,該線程會不斷地從QueueEvent中取出用戶消息,並進行一定的過濾,過濾後,在將這些消息發送給當前活動的客戶端程序中.
    二,客戶端
    客戶端主要包括以下重要類:
  • ActivityThread類:該類爲應用程序的主線程類,所有的APK程序都有且一個ActivityThread類,程序的入口爲該類中的static main()函數,ActivityThread所在的線程即爲UI線程或者爲主線程
  • Activity類:該類爲APK的一個最小運行單元.換句話說就是主線程動態加載可執行代碼的最小單元類,一個APK程序中可以包含多個Activity對象,ActivityThread主類會根據用戶操作選擇動態加載哪個Activity對象
  • PhomeWindow類:該類繼承於Window類,同時,PhoneWindow類內部包含一個DecorView對象,DecorView的父類是FrameLayout,因此PhoneWindow是內涵一個View對象,並提供了一組通過窗口的API;
  • Window類:該類提供了一組通用的窗口(Window)操作API.這裏的窗口僅僅是客戶端程序層面上的,Wms所管理的窗口並不是Window類,而是一個View或者是一個ViewGroup類,對於PhoneWindow類而言就是其內部包含的DecorView類.Window是一個abstract類型. 是一個抽象類
  • DecorView類:該類是一個FrameLayout的子類,並且是PhoneWindow種的一個內部類,DecorView的英文是Decoration,即”修飾”的意思,DecorView就是對普通的FrameLayout進行了一定的修飾,比如添加一個通用的Title bar,並響應特定的按鈕信息等;
  • ViewRoot類:Wms管理客戶端窗口時,需要通知客戶端進行某種操作,這些都是通過IPC調用完成的,而在客戶端窗口收到IPC調用後,都會把該調用轉換爲本地的一個異步調用,實現的方式就是使用Handler,ViewRoot就是繼承於Handler,其中作用主要是把Wms的IPC調用轉換爲本地的一個異步調用.
  • W類:該類繼承與Binder,並且是VIewRoot的一個內部類,Wms通知客戶端窗口時,是通過IPC調用,也就是調用到該Binder類,然後改Binder內部的處理函數一般會給該類所在的ViewRoot類發送一個Handler消息,以便進行異步處理.
  • WindowManager類:客戶端要申請創建一個窗口,而具體創建窗口的任務是由WmS完成的.WindowManager類就像是一個部門經理,誰有什麼需求就告訴他,由它和Wms進行交互,客戶端不嫩直接Wms進行交互.

Linux驅動

Linux驅動和FrameWork相關的主要包括兩個部分,分別是SurfaceFlingger(SF)和Binder,每個窗口對應一個Surface,SF驅動的重用是把各個Surface顯示在同一個屏幕上.
Binder驅動的作用是提供跨進程的消息傳遞,消息傳遞過程可以參照我的Android內核之Binder

APK程序的執行過程
首先,ActivityThrad從main()函數中開始執行,調用prepareMainLooper()爲UI線程創建一個消息隊裏(MessageQueue).
然後創建一個ActivityThread對象,在ActivityThread的初始化代碼中H(Handler)對象和一個Application對象(Binder)對象,其中Binder對象負責接收遠程AmSterdam的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類,創建了ViewRoot類後,WindowManager在調用Wms的遠程接口完成添加一個窗口並顯示到屏幕上.
接下來,用戶開始在程序界面上操作.KeyQ線程不斷把用戶消息存儲到QueueEvent隊列中,InputDispatcherThread線程逐個取出信息,然後調用WmS中的響應函數處理該消息。當WmS發現該消息屬於客戶端某個窗口時,就會調出相應窗口的W接口。
W類是一個Binder,負責接收WmS的IPC調用,並把調用消息傳遞給ViewRoot,ViewRoot再把消息傳遞給UI主線程ActivityThread,ActivityThread解析該消息並作出響應的處理。在客戶端程序中,首先處理消息的是DecorView,如果DecorView不想處理某個消息,則可以將這個消息傳遞給其內部包含的子View或者ViewGroup,如果還沒有處理,則傳遞給PhoneWindow,最後在傳遞給Activity。
客戶端中的線程
在多線程操作系統中,任何程序都在運行在線程之中。系統首先會爲客戶端程序分配一個線程,然後改線程從程序的入口處開始執行。那麼Android系統都有哪些線程?什麼是UI線程?程序自定義Thread和UI線程有區別是什麼?
首先,很明確地講,包含有Activity的客戶端至少包含三個線程。每個Binder對象都對應一個線程,Activity啓動後創建一個ViewRoot,W 對象,同時ActivityThread會創建一個ApplicationThread對象,這兩個對象繼承於Binder,因此會啓動兩個線程,負責接收Linux Binder驅動發送IPC調用,最後一個主要的線程也就是程序本身所在的線程,也叫用戶交互(UI)線程,因爲所有的處理用戶消息,以及繪製界面的工作都在該線程中完成。Android程序中的線程
在上邊的圖片中我們看到了這麼幾個方Native狀態的線程:分別是main,Binder1,Binder2,從這個圖片中我們就可以看出自定義的Thread和UI線程的區別在於,UI線程是從ActivityThread運行的,在該類彙總的main()方法中,已經使用LoopareMainLooper()爲該線程添加了Looper對象,即已經爲該線程創建了消息隊列(MessageQueue),因此,程序員纔可以在Activity中定義Handler對象(因爲聲明Handler對象時,所在的線程必須創建MessageQueue).而普通的自定義Thread是一個裸線程,因此不能直接在Thread中定義Handler對象,從而使用場景來講,即不能直接給Thread對象發消息,但可以給UI線程發消息

Activity之間是如何傳遞消息(數據)

首先,提出這個問題是因爲,我們需要不同Activity之間傳遞數據,然而這個問題本身就有問題,所謂”傳遞消息”一般是指多個線程之間的,而Activity本身並不是線程,ActivityThread纔是一個JAVA類而已,就像Rectangle,Trigle類一樣,如果有人問你他兩要怎麼傳遞消息你會不會覺得很奇怪?
事實上,如果要在兩個類中傳遞數據,方法有很多 .
方法一:可以現實實例化某個類,獲得該類的引用,當其他類需要該對象內部數據時,可以直接通過引用去訪問該類的內部數據.
方法二:對於A,B兩個類之間,可以先實例化一個第三方類C,然後兩個類都可以把需要傳遞的數據存入C中,或者從C中取出.
這些方法理論上都可以在Activity類之間傳遞數據,然而,與普通類傳遞數據有所不同,普通類的實例化都是成員顯示完成的,而Activity類的實例化卻是由FrameWork完成的,程序員只能使用startActivity()方法來告訴FrameWork去運行哪個Activity,這就意味着程序員不能得到Activity對象的引用,那麼久不能直接訪問額你不數據,解決這個問題的方法就是Activity.getApplication()函數,該函數能夠返回一個Application對象,該Application對象在該程序中是唯一的,同一個程序中不同的Activity調用該函數返回的Application對象是相同的,該對象的名稱可以在AndroidManifest.xml中指定,一旦獲取了該Application對象,就可以借組該對象,在不同的Activity之間傳遞數據.
除此之外,FrameWork本身也提供了標準的Activity之間傳遞數據的方法,即Intent類,該類作爲startActivity()參數,僅用於啓動Activity時傳遞給目標Activity,同時,如果調用startActivityResult(),目標Activity結束後,也會返回一個Intent對象給原Activity.
另外,從設計理念的角度來看,Android認爲,兩個Activity如果要共享數據,可以通過PerferenceStorage或者文件,數據庫進行,同時一般情況下,設備上只會有一個Activity在允許,因此,多個Activity之間傳遞數據也不是必須的,如果某個Activity需要在停止後還能處理數據,那麼該Activity似乎更應該設計一個後臺Thread或者一個Service都很容易獲得引用.

窗口相關類的概念

  • 窗口(非Window類):這是一個春雨發的說法,即程序員看到的屏幕上某個獨立的界面,比如一個帶有Title Bar的Activity界面,一個對話框,一個Menu菜單等,這些都能稱爲窗口, 在Android的引文相關文檔使用的是Window這個單詞,而從Wms的角度來講,窗口是接收用戶消息的最小單元,Wms內部用特定的類表示一個窗口,而給Wms中添加一個窗口是調用WindowManager類的addView()方法,也就是說,從WmS的角度來看,所謂添加一個窗口實際上是添加一個View對象,以至於這個View對象是來自於Activity還是用戶自定義的一個View都不是很重要,Wms接收用戶消息後,首先要判斷這個消息屬於哪個窗口,即哪個View對象,然後同IPC調用這個消息傳遞給客戶端的ViewRoot子類.
  • Window類:該類在android.view包中, 是一個abstract類,該類抽象了”客戶端窗口”的基本操作,並且定義了一組Callback接口,Activity類就是通過實現這個Callback接口以獲得對象消息處理的機會的,因爲消息最初是由WmS傳遞給View對象的
  • ViewRoot類:該類在android.view包中,客戶端申請創建窗口時需要一個客戶端代理,用以和WmS進行交互,ViewRoot內部類W就是完成p這個功能的,Wms所管理的每一個窗口都會對應一個ViewRoot類.
  • W類:該類是ViewRoot的一個內部類,繼承與Binder,用於向WmS提供一個IPC接口,從而讓WmS控制窗口客戶端的行爲
    描述一個窗口之所以使用這麼多類的原因在於,窗口的概念存在於客戶端和服務端(Wms)之中,並且FrameWork又定義了一個Window類,這讓人容易產生混淆,實際上WmS所管理的窗口和Window類沒有任何關係.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章