1. 程式人生 > >Activity啟動流程筆記

Activity啟動流程筆記

一直遇到這個問題,而且提示與生命週期不同,很是疑惑。於是網上搜羅,並翻看《Android開發藝術探索》,發現多是程式碼,長篇大論。好奇心所致,一路ctrl+B,看看能收穫些什麼。

Activity的啟動流程,涉及應用程序端和系統服務端兩部分,因此,為跨程序通訊。既然是跨程序,那就離不開AndroidBinder機制。

Binder機制,為C/S模式,是單向的。而應用程序端與系統服務端的通訊是雙向的,互為Client/Server。所以,需要兩個BinderActivityManagerNativeApplicationThreadNative就是這兩個Binder。先說一下,這兩Binder及其子類。

ActivityManagerNative

ActivityManagerNative繼承自Binder,實現了IActivityManager介面(該介面定義了與Activity manager Service通訊的介面)。ActivityManagerNative還包含一個內部類ActivityManagerProxy。但ActivityManagerNative仍是一個抽象類。

ActivityManagerService

ActivityManagerService繼承於ActivityManagerNative,並實現了內部的抽象方法。該類物件位於系統程序中。

因此,ActivityManagerProxy

物件可以看做是ActivityManagerService在應用程序端的代理。可以通過ActivityManagerNativegetDefault靜態方法來獲取到該代理。

通過呼叫ActivityManagerProxy物件所提供的方法,完成應用程序端至系統服務端的通訊。

ApplicationThreadNative

ApplicationThreadNative繼承自Binder,實現了IApplicationThread介面(該介面定義了與Application通訊的介面)。ApplicationThreadNative也包含一個內部類ApplicationThreadProxyApplicationThreadNative

也是一個抽象類。

ApplicationThread

ApplicationThread繼承自ApplicationThreadNative,並實現了內部抽象方法。

ApplicationThreadActivityThread的一個內部私有類。

ActivityThread是應用的主執行緒。

ActivityThread還存在一個內部私有類H,實為Handler,用於處理內部訊息。

通過呼叫ApplicationThreadProxy物件所提供的方法,完成系統服務端至應用程序端的通訊。

由於ApplicationThreadActivityManagerService的存在,使得雙向通訊得以完成。

與生命週期的關係

Activity的啟動,涉及android framework,需要閱讀核心程式碼,且程式碼十分繁瑣。因此,對於其流程,也只能看一下順序,瞭解個大概的機制。

結合Activity的生命週期,整個流程大致分以下幾步:

(1)執行棧頂activityonPause

(2)檢視當前要啟動的目標activity所在程序是否被建立。若未建立則,則執行步驟(3);否則,跳至步驟(4);

(3)啟動activity所在程序;

(4)依次觸發activity的生命週期方法,onCreateonStartonResume

(5)觸發原棧頂activityonStop方法。

但,畢竟啟動過程,不僅僅是生命週期方法的呼叫。硬著頭皮,捋著程式碼走了一遍。才有了以下筆記。希望有助於記憶。

參考

整理過程中,參考了部分文章,也列在下面。

文中有部分描述還是模糊,仍需要檢視程式碼,才得以確認。

此外,對於android framework程式碼,若不想下載,可訪問網址

線上檢視。只需要輸入要查詢的類即可,很方便。

小結

先把小結寫在前面,時因為整個Go To Definition過程多少有些乏味和漫長。

這個過程中,會在ActivityThread(將要啟動的Activity),ActivityThread(當前處於棧頂的Activity)和ActivityManagerService間不斷的跳轉。因為前兩者是不同的程序,不能直接通訊,所以需要系統服務程序ActivityManagerService這個管理者出現,為兩者傳遞資訊。

系統核心程序zygote,也會參與到啟動過程中。當將要啟動的Activity所在的程序未被啟動時,zygote將建立該程序。

1)呼叫startActivity時,當前程序會通過ActivityManagerProxyAMS(ActivityManagerService)傳送資訊。通知其執行當前棧頂的ActivityonPause

2AMS收到請求後,通過ApplicationThreadProxy向當前棧頂ActivityActivityThread傳送資訊。

3)當前棧頂ActivityActivityThread接收到請求後,傳送messageHH觸發該ActivityonPause。執行完畢後,當前棧頂ActivityActivityThread,通過ActivityManagerProxy通知AMS(ActivityManagerService),操作完成。

4AMS收到請求後,檢視將要啟動的目標Activity所在程序是否已被啟動。若未啟動,則通知系統核心zygote建立程序,並將程序啟動類ActivityThread名稱作為引數,提供給zygote.

5zygote建立完程序後,觸發ActivityThreadMain方法,初始化程序。初始化結束後,ActivityThread通過ActivityManagerProxy通知AMS(ActivityManagerService)操作完畢。

6AMS收到請求後,通過ApplicationThreadProxy向目標ActivityThread(新建成的)傳送請求,要求其啟動目標Activity

7)目標ActivityThread收到請求後,傳送messageHH依次觸發handleLaunchActivity操作,和handleResumeActivity操作。前者執行目標ActivityonCreateonStart,後者執行onResumehandleResumeActivity最後會再次通過ActivityManagerProxy通知AMS(ActivityManagerService),進行Idle操作。

8AMS接收請求後,會在空閒時通過ApplicationThreadProxyt通知原棧頂ActivityActivityThread,對原棧頂Activity執行onPause操作。或在記憶體不足時,執行onSaveInstanceState操作。

整個流程小結完畢。

Go to Definition

下面是走流程時做的筆記。

1)棧頂activityonPause

啟動一個Activity,是從startActivity()法開始的逐級呼叫。

startActivity
        ->startActivityForResult
                ->Instrumentation.execStartActivity
                        ->ActivityManagerNative.getDefault().startActivity

InstrumentationActivity的一個應用程序端的實際操作類。

當呼叫ActivityManagerNative.getDefault().startActivity時,根據Binder機制,實際是呼叫了ActivityManagerService物件的startActivity方法。操作從應用程序端,跳轉至系統服務端。

ActivityManagerService.startActivity 
        ->startActivityAsUser
                ->StackSupervisor.startActivityMayWait
                        -> StackSupervisor.startActivityLocked
                                -> StackSupervisor.startActivityUncheckedLocked
                                        -> ActivityStack.startActivityLocked
                                                -> ActivityStackSupervisor.resumeTopActivitiesLocked
                                                        ->ActivityStack.resumeTopActivityLocked 
                                                                ->ActivityStack.startPausingLocked
                                                                        -> prev.app.thread.schedulePauseActivity

prev.app.thread為一個IApplicationThread物件,即ApplicationThreadProxy物件。

因此,此時操作又從系統服務端,跳轉至應用程序端。該程序為棧頂Activity所在的程序。繼續,

ApplicationThread.schedulePauseActivity
        ->ActivityThread.sendMessage (PAUSE_ACTIVITY_FINISHING)
                ->H.sendMessage
                        ->H.handleMessage
                                ->ActivityThread.handlePauseActivity
                                        ->ActivityThread.performPauseActivity
                                                ->mInstrumentation.callActivityOnPause
                                                        ->activity.performPause
                                        ->ActivityManagerNative.getDefault().activityPaused

在應用程序中ApplicationThread傳送PAUSE_ACTIVITY_FINISHING訊息至HH處理後觸發mInstrumentation最終呼叫了activity.performPause方法。

至此棧頂activity 應用程序端的Pause處理結束。

2啟動目標Activity所在程序。

在上一階段的ActivityThread.handlePauseActivity方法中處理完應用程序端的Pause處理後還呼叫了ActivityManagerNative.getDefault().activityPaused使得處理流程再次從應用程序跳轉至系統服務端。

ActivityManagerService.activityPaused
        ->ActivityStack.activityPausedLocked
                ->ActivityStack.completePauseLocked
                        ->ActivityStackSupervisor.resumeTopActivitiesLocked
                                ->ActivityStack.resumeTopActivityLocked
                                        ->ActivityStack.resumeTopActivityInnerLocked
                                                ->ActivityStackSupervisor.startSpecificActivityLocked
                                                        ->ActivityStackSupervisor.realStartActivityLocked
                                                        Or
                                                        ->mService.startProcessLocked

其中,ActivityStackSupervisor.startSpecificActivityLocked方法會判斷一下需要啟動的目標Activity所在應用程序是否已經啟動若啟動的話則直接呼叫ActivityStackSupervisor.realStartActivityLocked方法觸發目標Activity的生命週期否則呼叫mServicestartProcessLocked方法用於啟動應用程序。

mService是什麼一個ActivityManagerService物件。

因此,在目標Activity所在應用程序未被啟動的情況下呼叫StartProcessLocked方法時操作又從應用程序轉至系統服務端。

ActivityManagerService. startProcessLocked
        ->Process.start
                -> Process.startViaZygote
                        ->Process.zygoteSendArgsAndGetResult

Zygoteandroid系統中用於建立新程序的核心程序。每個程序都有一個啟動類。

程序的啟動類名“android.app.ActivityThread”被當做引數,在Process.start方法中設定,並傳入Process.startViaZygote中。

當新程序建立完畢後,會依照啟動類名反射至啟動類,並自動執行程序啟動類的main方法。即ActivityThreadmain方法。

ActivityThread.main
        ->new ActivityThread
                -> ActivityThread.attach
                        -> ActivityManagerNative.getDefault.attachApplication

再次跳轉至ActivityManagerService中。

ActivityManagerService.attachApplicationLocked
              ->ActivityStackSupervisor.attachApplicationLocked
                      ->ActivityStackSupervisor.realStartActivityLocked

又見到realStartActivityLocked方法了。之前提過,該方法是用於啟動Activity的。因此,說明從當前位置開始,將進行目標activity的生命週期操作。程序啟動操作完畢。

3)啟動Activity

ActivityStackSupervisor.realStartActivityLocked
        ->app.thread.scheduleLaunchActivity

操作從系統服務端跳轉至應用程序端。

ActivityThread.scheduleLaunchActivity
        ->sendMessage(H.LAUNCH_ACTIVITY)
                ->H.handleMessage
                        ->ActivityThread.handleLaunchActivity
                                ->ActivityThread.performLaunchActivity
                                        ->mInstrumentation.callActivityOnCreate
                                                ->activity.performCreate
                                                        ->activity.onCreate
                                        ->activity.performStart
                                                ->mInstrumentation.callActivityOnStart
                                                        -> activity.onStart
                                ->ActivityThread.handleResumeActivity
                                        ->ActivityThread.performResumeActivity
                                                ->r.activity.performResume
                                                        ->mInstrumentation.callActivityOnResume
                                                                ->activity.onResume
                                        ->Looper.myQueue().addIdleHandler(new Idle)

從過程中可以看到,在處理LAUNCH_ACTIVITY訊息時,handler執行了ActivityThread.handleLaunchActivity方法。該方法依次執行了兩個方法,ActivityThread.performLaunchActivity和ActivityThread.handleResumeActivity。前者觸發了目標activityonCreate方法,和onStart方法。而後者,則觸發了activityonResume方法。

至此Activity完成顯示。但這並未結束。此前棧頂的activity還有操作未完成。

4)執行棧頂ActivityonStop

在處理目標activity onResume生命週期的handleResumeActivity方法中,結尾處,呼叫了Looper.myQueue().addIdleHandler(new Idler())。這個方法很不起眼,但卻觸發了空閒情況下的處理機制。

Idler繼承於MessageQueue.IdleHandler。用於線上程空閒時,執行某種操作。空閒時,其queueIdle方法將被觸發。

Idler.queueIdle
        ->ActivityManagerNative.getDefault().activityIdle

又是一個熟悉的身影~再次跳轉至系統服務端。

ActivityManagerService.activityIdle
                ->ActivityStack.stopActivityLocked() 
                        ->r.app.thread.scheduleStopActivity

再次跳轉至應用程序端,原置頂activity所在的程序。

ActivityThread.scheduleStopActivity
       -> ActivityThread.sendMessage
              ->H.handleMessage
                     ->ActivityThread.handleStopActivity
                            -> ActivityThread.performStopActivityInner
                                   ->ActivityThread.callCallActivityOnSaveInstanceState
                                   or
                                   ->Activity.performStop

ActivityThread.performStopActivityInner方法中,根據情況,會觸發兩個不同的操作。若記憶體不足,需要回收,則觸發ActivityThread.callCallActivityOnSaveInstanceState;而正常情況下,則會觸發Activity.performStop。

我們先來看一下正常情況。

Activity.performStop
       ->mInstrumentation.callActivityOnStop
              ->Activity.onStop

終於,onStop出現。 原棧頂activity的onStop完成。

再來看,記憶體不足的情況。

ActivityThread.callCallActivityOnSaveInstanceState
       ->mInstrumentation.callActivityOnSaveInstanceState
              ->Activity.performSaveInstanceState
                     ->Activity.onSaveInstanceState

原棧頂activity的onSaveInstanceState方法完成。

至此,整個Activity的啟動完畢。