1. 程式人生 > >寫給Android App開發人員看的Android底層知識(3)

寫給Android App開發人員看的Android底層知識(3)

       (七)App啟動流程第2篇

       書接上文,App啟動一共有七個階段,上篇文章篇幅所限,我們只看了第一階段,接下來講剩餘的六個階段,仍然是拿鬥魚App舉例子。

       簡單回顧一下第一階段的流程,就是Launcher向AMS傳送一個跨程序通訊,通過AMN/AMP,告訴AMS,我要啟動鬥魚App。

       畫一個圖,描述一下啟動App所經歷的7個階段:

第2階段 AMS處理Launcher傳過來的資訊

這個階段主要是Binder的Server端在做事情。因為我們是沒有機會修改Binder的Server端邏輯的,所以這個階段看起來非常枯燥,我儘量說的簡單些。

  1. 首先Binder,也就是AMN/AMP,和AMS通訊,肯定每次是做不同的事情,就比如說這次Launcher要啟動鬥魚App,那麼會發送型別為START_ACTIVITY——TRANSACTION的請求給AMS,同時會告訴AMS要啟動哪個Activity。
  2. AMS說,好,我知道了,然後它會幹一件很有趣的事情,就是檢查鬥魚App中的Manifest檔案,是否存在要啟動的Activity。如果不存在,就丟擲Activity not found的錯誤,各位做App的同學對這個異常應該再熟悉不過了,經常寫了個Activity而忘記在Manifest中聲明瞭,就報這個錯,就是因為AMS在這裡做檢查。不管是新啟動一個App的首頁,還是在App內部跳轉到另一個Activity,都會做這個檢查。
  3. 但是Launcher還活著啊,所以接下來AMS會通知Launcher,哥們兒沒你什麼事了,你“停薪留職”吧。那麼AMS是通過什麼途徑告訴Launcher的呢?

       前面講過,Binder的雙方進行通訊是平等的,誰發訊息,誰就是Client,接收的一方就是Server。Client這邊會呼叫Server的代理物件。

       對於從Launcher發來的訊息,通過AMS的代理物件AMP,傳送給AMS。

       那麼當AMS想給Launcher發訊息,又該怎麼辦呢?前面不是把Launcher以及它所在的程序給傳過來了嗎?它在AMS這邊儲存為一個ActivityRecord物件,這個物件裡面有一個ApplicationThreadProxy,單單從名字看就出賣了它,這就是一個Binder代理物件。它的Binder真身,也就是ApplicationThread。

       站在AIDL的角度,來畫這張圖,是這樣的:

所以結論是,AMS通過ApplicationThreadProxy傳送訊息,而App端則是通過ApplicationThread來接收這個訊息。

      第3階段 Launcher去休眠,然後通知AMS,我真的已經“停薪留職”了,沒有吃空餉

ApplicationThread(簡稱APT),它和ApplicationThreadProxy(簡稱ATP)的關係,我們在第三階段已經介紹過了。

      APT接收到來自AMS的訊息後,就呼叫ActivityThread的sendMessage方法,向Launcher的主執行緒訊息佇列傳送一個PAUSE_ACTIVITY訊息。

      前面說過,ActivityThread就是主執行緒(UI執行緒)

      看到下面的程式碼是不是很親切?

傳送訊息是通過一個名為H的Handler類的完成的,這個H類的名字真特麼有個性,想記不住都難。

      做App的同學都知道,繼承自Handler類的子類,就要實現handleMessage方法,這裡是一個switch…case語句,處理各種各樣的訊息,PAUSE_ACTIVITY訊息只是其中一種,由此也能預見到,AMS給Activity傳送的所有訊息,以及給其它三大元件傳送的所有訊息,都從H這裡經過,為什麼要強調這一點呢,既然四大元件都走這條路,那麼這裡就可以做點手腳,從而做外掛化技術,這個我們以後介紹外掛化技術的時候會講到。

H對於PAUSE_ACTIVITY訊息的處理,如上面的程式碼,是呼叫ActivityThread的handlePauseActivity方法。這個方法幹兩件事:

  •    ActivityThread裡面有一個mActivities集合,儲存當前App也就是Launcher中所有開啟的Activity,把它找出來,讓它休眠。
  •    通過AMP通知AMS,我真的休眠了。

      你可能會找不到H和APT這兩個類檔案,那是因為它們都是ActivityThread的內嵌類。

      至此,Launcher的工作完成了。你可以看到在這個過程中,各個類都起到了什麼作用。芸芸眾生,粉墨登場:

  •    APT
  •    ActivityThread
  •    H

      第4階段 AMS啟動新的程序

      接下來又輪到AMS做事了,你們會發現我不太喜歡講解AMS的流程,甚至都不畫UML圖,因為這部分邏輯和App開發人員關係不是很大,我儘量說的簡單一些,把流程說清楚就好。

      AMS接下來要啟動鬥魚App的首頁,因為鬥魚App不在後臺程序中,所以要啟動一個新的程序。這裡呼叫的是Process.start方法,並且指定了ActivityThread的main函式為入口函式。

第5階段 新的程序啟動,以ActivityThread的main函式作為入口

啟動新程序,其實就是啟動一個新的App。

      在啟動新程序的時候,為這個程序建立ActivityThread物件,這就是我們耳熟能詳的主執行緒(UI執行緒)。

      建立好UI執行緒後,立刻進入ActivityThread的main函式,接下來要做2件具有重大意義的事情:

      1)建立一個主執行緒Looper,也就是MainLooper。看見沒,MainLooper就是在這裡建立的。

      2)建立Application。記住,Application是在這裡生成的。

- - - - - - - - - - - - - -華麗的分割線 開始- - - - - - - - - - - - - - -

      App開發人員對Application非常熟悉,因為我們可以在其中寫程式碼,進行一些全域性的控制,所以我們通常認為Application是掌控全域性的,其實Application的地位在App中並沒有那麼重要,它就是一個Context上下文,僅此而已。

      App中的靈魂是ActivityThread,也就是主執行緒,只是這個類對於App開發人員是訪問不到的——使用反射倒是可以修改這個類的一些行為。

- - - - - - - - - - - - - - -華麗的分割線 結束- - - - - - - - - - - - - - -

      建立新App的最後,就是告訴AMS,我啟動好了,同時把自己的ActivityThread物件傳送給AMS,從此以後,AMS的電話簿中就多了這個新的App的登記資訊,AMS以後向這個App傳送訊息,就通過這個ActivityThread物件。

     第6階段 AMS告訴新App啟動哪個Activity

     AMS把傳入的ActivityThread物件,轉為一個ApplicationThread物件,用於以後和這個App跨程序通訊。還記得APT和ATP的關係嗎?這就又回到第2階段的那張關係圖了。

     還記得第1階段,Launcher傳送給AMS要啟動鬥魚App的哪個Activity嗎?這個資訊被AMS存下來了。

     那麼在第6階段,AMS從過去的記錄中翻出來要啟動哪個Activity,然後通過ATP告訴App。

     第7階段 啟動鬥魚首頁Activity

      畢其功於一役,盡在第7階段。這是最後一步。

      App,這個Binder的另一端,通過APT接收到AMS的訊息,仍然是在H的handleMessage方法的switch語句中處理,只不過,這次訊息的型別是LAUNCH_ACTIVITY:

      ActivityClientRecord是什麼?這是AMS傳遞過來的要啟動的Activity。

      還是這裡,我們仔細看那個getPackageInfoNoCheck方法,這個方法會提取Apk中的所有資源,然後設定給r的packageInfo屬性。這個屬性的型別很有名,叫做LoadedApk。各位記住這裡,這個地方可以幹壞事,也是外掛化技術滲入的一個點。

      在H的這個分支中,又反過來回調ActivityThread的handleLaunchActivity方法,你要是覺得很繞那就對了。其實我一直覺得,ActivityThread和H合併成一個類也沒問題。

      重新看一下這個過程,每次都是APT執行ActivityThread的sendMessage方法,在這個方法中,把訊息拼裝一下,然後扔個H的swicth語句去分析,來決定要執行ActivityThread的那個方法。每次都是這樣,習慣就好了。

      handleLaunchActivity方法都做哪些事呢?

      1)通過Instrumentation的newActivity方法,創建出來要啟動的Activity例項。

      2)為這個Activity建立一個上下文Context物件,並與Activity進行關聯。

      3)通過Instrumentation的callActivityOnCreate方法,執行Activity的onCreate方法,從而啟動Activity。看到這裡是不是很熟悉很親切?

      至此,App啟動完畢。這個流程是經過了很多次握手, App和ASM,頻繁的向對方傳送訊息,而傳送訊息的機制,是建立在Binder的基礎之上的。

下一篇文章,我們講Context家族。

相關推薦

Android App開發人員Android底層知識1

這個系列的文章一共8篇,我醞釀了很多年,參考了很多資源,查看了很多原始碼,直到今天把它寫出來,也是戰戰兢兢,生怕什麼地方寫錯了,貽笑大方 (一)引言 早在我還是Android菜鳥的時候,有很多技術我都不太明白,也都找不到答案,比如apk是怎麼安裝的,比如資源是怎

Android App開發人員Android底層知識8

(十)PMS及App安裝過程        PMS,全稱PackageManagerService,是用來獲取Apk包的資訊的。        在前面分析四大元件與AMS通訊的時候,我們介紹過,AMS總是會使用PMS載入包的資訊,將其封裝在LoadedApk這個類物件

Android App開發人員Android底層知識7

(十二)ContentProvider (1)ContentProvider是什麼? ContentProvider,簡稱CP。 做App開發的同學,尤其是電商類App,對CP並不熟悉,對這個概念的最大程度的瞭解,也僅僅是建立在書本上,它是Android四大元件中的一個。 做系統管理類的App,比

Android App開發人員Android底層知識5

     (十)Service      Service有兩套流程,一套是啟動流程,另一套是繫結流程。我們做App開發的同學都應該知道。            1)在新程序啟動Service        我們先看Service啟動過程,假設要啟動的Service是在一個新的程序中,分為5個階段:

Android App開發人員Android底層知識4

(八)App內部的頁面跳轉       在介紹完App的啟動流程後,我們發現,其實就是啟動一個App的首頁。       接下來我們看App內部頁面的跳轉。       從ActivityA跳轉到ActivityB,其實可以把ActivityA看作是Launcher,那麼這個跳轉過程,和Ap

Android App開發人員Android底層知識3

       (七)App啟動流程第2篇        書接上文,App啟動一共有七個階段,上篇文章篇幅所限,我們只看了第一階段,接下來講剩餘的六個階段,仍然是拿鬥魚App舉例子。        簡單回顧一下第一階段的流程,就是Launcher向AMS傳送一個跨程序通訊,通過AMN/AMP,告訴A

Android App開發人員Android底層知識2

(五)AMS 如果站在四大元件的角度來看,AMS就是Binder中的Server。       AMS全稱是ActivityManagerService,看字面意思是管理Activity的,但其實四大元件都歸它管。估計是Android底層開發人員先寫了ActivityManagerService用來管理A

Android App開發人員Android底層知識6

(十一)BroadcastReceiver BroadcastReceiver,也就是廣播,簡稱Receiver。      很多App開發人員表示,從來沒用過Receiver。其實吧,對於音樂播放類App,用Service和Receiver還是蠻多的,如果你用過QQ音樂,App退到後臺,音樂照樣播放

初次接觸Android APP開發之安裝Android studio軟體出現的問題以及解決方案錯誤史,一把辛酸淚

     序言     筆者由於心血來潮,想玩玩Android開發。本想著用eclipes開發Android APP。但是發現網上說eclipes不是最好的選擇,所以筆者就放棄了熟悉的eclipes來開發Android APP,改用Android studio。在此之前,筆

Android應用開發:網絡工具——Volley

respond sid 開發 多少 called creat miss 相等 eal 引言 在Android應用開發:網絡工具——Volley(一)中結合Cloudant服務介紹了Volley的一般使用方法,當中包括了兩種請求類型StringRequest和JsonOb

Android應用開發:網絡工具——Volley

要求 com 庫文件 urn welcom 順序 之前 air tin 引言 網絡一直是我個人的盲點,前一陣子抽空學習了一下Volley網絡工具的用法,也透過源代碼進行了進一步的學習,有一些心得想分享出來。在Android開發中,成熟的網絡工具不少,And

Android安全/開發基礎--8--Java本地介面JNI

8-1、JNI概述 JNI的本意是Java Native Interface(Java本地介面),是為了方便Java和C/C++等原生代碼所封裝的一層介面,使用JNI技術可以對Java層遮蔽不同作業系統平臺之間的差異,從而實現Java本身的平臺無關特性。JNI和

Android應用開發以及設計思想深度剖析1

本文內容,主題是透過應用程式來分析Android系統的設計原理與構架。我們先會簡單介紹一下Android裡的應用程式程式設計,然後以這些應用程 序在執行環境上的需求來分析出,為什麼我們的Android系統需要今天這樣的設計方案,這樣的設計會有怎樣的意義, Android究竟

一個android專案開發遇到的各種小問題

1、map格式字串如何解析? 藉助json,先將字串轉化為json格式,再取值 JSONObject object = new JSONObject(posMap); clientIden = object.getString("iden"); ---------

【安卓-自定義佈局】安卓App開發思路 一步一個腳印實現內嵌在app中的webview 騰訊開源X5 高效安全

實現內嵌在app中的webview 採用騰訊開源X5 高效安全 webview在app的使用中,十分頻繁,原生的webview載入速度相對來說很慢,而且很費流量。騰訊開源了x5的webview

【安卓-自定義佈局】安卓App開發思路 一步一個腳印實現自定義滾動的新聞條目上下滾動-仿蘑菇街

實現自定義滾動的新聞條目上下滾動-仿蘑菇街       這種上下滾動的自定義佈局,就像是公告那種上下的翻滾,一般為文字的滾動,很明顯,就是自定義佈局,一般是線性佈局。這裡提到的安卓原生的控制元件自然是

Android 從零學資料結構與演算法3——HashMap和LinkedHashMap

    本部落格的原創文章,都是本人平時學習所做的筆記,不做商業用途,如有侵犯您的智慧財產權和版權問題,請通知本人,本人會即時做出處理刪除文章。HashMap    基於雜湊表(散列表)的Map介面的實現,允許使用null鍵和null值,HashMap是非執行緒安全的,資料元

遊戲開發中必備的數學知識——矩陣的基本變換

基本變換 使用Direct3D程式設計的時候,我們使用4×4的矩陣表示一個變換。其思路如下: 設定一個4×4的矩陣中元素的值,使其表示某一個具體變換,然後我們將某一點的座標或者某向量的分量放入一個1×4的行向量v中,乘積vX就是成為了一個新的經過變換的向量v。 此時,我們之所以使用4×4

Flex開發流程設計器的經驗之談3

Model—— 實現對Model介面的宣告,以及對Model變更的時候做Notifer響應機制的實現。 Flex Extention—— 擴充套件了一些Flex Controls和Containers做,來輔助檢視顯示。

java開發需要知道的linux知識

water RoCE ESS xshel watermark ref process 網上 .sh 做為一個後端開發,經常需要上服務器上看看哪裏出問題了,又報什麽錯了,所以對程序員的服務器技能提出了一定的要求,要學到專業運維那個程度肯定是不可能的,我們只用掌握常用的的些就可