国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

圖解Activity的啟動過程

2019-11-07 23:02:10
字體:
來源:轉載
供稿:網友

由于Activity的啟動涉及大量ipC和Binder方面的知識,因此了解這方面的知識后再來看Activity啟動的相關源碼可能不會那么吃力。

Activity啟動的相關類和概要

Activity啟動時涉及到的類有IActivityManager相關類, IapplicationThread相關類, ActivityManagerService相關類。

IActivityManager相關類

Activity的管理采用binder機制,管理Activity的接口是IActivityManager。ActivityManagerService實現了Activity管理功能,位于system_server進程。從ActivityManagerService提供的接口來看,它負責管理Activity的啟動和生命周期。

ActivityManagerPRoxy對象是ActivityManagerService在普通應用進程的一個代理對象,應用進程通過ActivityManagerProxy對象調用ActivityManagerService提供的功能。應用進程并不會直接創建ActivityManagerProxy對象,而是通過調用ActiviyManagerNative類的工具方法getDefault方法得到ActivityManagerProxy對象。所以在應用進程里通常這樣啟動Activty:

ActivityManagerNative.getDefault().startActivity()

IActivityManager

IApplicationThread相關類

應用進程需要調用ActivityManagerService提供的功能,返過來,ActivityManagerService也需要調用應用進程的回調操作以達到控制和調配應用進程的目的。因此,ActivityManagerService也有一個Binder對象–ApplicationThreadProxy,它是IApplicationThread的代理對象。

ApplicationThread類實現了IApplicationThread接口,實現了管理應用的操作,ApplicationThread對象運行在應用進程里,內部包含了大量啟動和停止Activity的接口,此外還包含了啟動和停止服務的接口。但因為ApplicationThread運行在Binder線程,這些接口方法大多都通過Handler傳給ActivityThread的內部的H來執行。

其實,ApplicationThread是ActivityThread的內部類,H其實是一個Handler,也是ActivityThread的一個內部類,運行在主線程。對于每一個應用程序來說,都有一個ActivityThread來表示一個應用主線程。

IApplicationThread 總的來說ActivityManagerService,ApplicationThread和ActivityThread之間的關系。ActivityManagerService可以說是Activity的啟動入口,相當于主國。ApplicationThread相當于外交官,作為ActivityManagerService與ActivityThread之間的信使,負責將ActivityManagerService下達的指令呈給ActivityThread的H來處理,以及將ActivityThread的調用請求傳給ActivityManagerService。ActivityThread則相當于諸侯國,對自己轄區內(應用進程)的Activity有直接的控制權,承擔Activity啟動的大部分工作,但Activity的戶口(ActivityStack)在ActivityManagerService手里。因為ActivityManagerService需要統一調控不同應用進程中的Activity。

啟動過程概述

無論是通過Launcher來啟動Activity還是通過父Activity來啟動Activity,都需要通過IPC調用ActivityManagerService的startActivity的方法。ActivityManagerService調用ActivityStarter.startActivityMayWait。經過一系列復雜的調用,收集并記錄Activity的啟動信息,調整ActivityStack(讓棧頂的Activity進入pause狀態),創建并初始化Application對象(如果有必要的話),創建ActivityThread并調用main方法(如果有必要的話)。最后在ActivityStackSupervisor的realStartActivityLocked方法調用app.thread.scheduleLaunchActivity方法。也就是說,ActivityManagerService調用ApplicationThread的scheduleLaunchActivity接口方法。ApplicationThread將這個啟動信息通過Handler轉發給ActivityThread(H)。ActivityThread通過ClassLoader加載相應的Activity類,調用Activity的onCreate方法。

startActivity

ActivityManagerService宏觀調控

Step1: Instrumentation#execStartActivity

系統每一次啟動Activity,先調用Instrumentation的execStartActivity方法。Instrumentation是負責監控Activity與系統的交互操作的,相當于系統運行日志,因此要啟動activity或回調activity的生命周期的方法時,都會先調用Instrumentation相關方法。

Instrumentation

public ActivityResult execStartActivity( ... try { int result = ActivityManagerNative.getDefault() .startActivity(whoThread, who.getBasePackageName(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mWho : null, requestCode, 0, null, options); checkStartActivityResult(result, intent); } catch (RemoteException e) { } return null; }

Step2: ActivityManagerService#startActivity

經過IPC調用,啟動Activity的指令來到了ActivityManagerService,緊接著AMS調用startActivityAsUser著手Activity的啟動工作。

Step3: ActivityStarter#startActiviytMayWait

AMS有一個ActivityStack,負責Activity的調度工作,比如維護回退棧。但ActivityStack內的Activity是抽象成ActivityRecord來管理的。Activity對象不會存在于AMS當中。

ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();

由于Activity之間的調度關系受很多因素的影響而變得非常復雜,Google使用了ActivityStack和ActivityStackSupervisor,以及Android 7.0添加的ActivityStarter來管理Activity的調度工作。此三者的調用過程如下圖:

這里寫圖片描述

由于它們之間調用過程比較復雜,下面只從挑重點來看。

ActivityStarter#startActivityMayWait

final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IVoiceInteractionsession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config, Bundle bOptions, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, TaskRecord inTask) { ... // Collect information about the target of the Intent. ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo); ... final ActivityRecord[] outRecord = new ActivityRecord[1]; int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, container, inTask); ... }

startActivityMayWait這個方法會創建ActivityRecord對象,再調用startActivityLocked。

ActivityStarter#startActivityUncheckedLocked

這個方法會根據Activity啟動信息(提取封裝到ActivityInfo類中)中的launchMode,flag等屬性來調度ActivityStack中的Task和ActivityRecord。因此這個方法是理解Activity啟動模式的關鍵。

ActivityStack#resumeTopActivityInnerLocked

這個方法內部會把前臺處于Resume狀態的Activity變成Pause狀態后才會繼續啟動Activity的邏輯。

將一個Activity變成Pause狀態需要經歷的調用于后面的啟動調用非常相似。

startPausingLocked->ApplicationThread.schedulePauseActivity->mH.sendMessage->ActivityThread.handlePauseActivity->ActivityManagerService.activityPaused->ActivityStack.activityPausedLocked->ActivityStack.completePauseLocked。

在completePauseLocked方法中又一次調用:

mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);

又回到了resumeTopActivityInnerLocked方法中,這時會調用ActivityStack.startSpecificActivityLocked方法。

ActivityStack#startSpecificActivityLocked

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) { // Is this activity's application already running? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid); if (app != null && app.thread != null) { try { ... realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { ... } } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }

這里最后會調用AMS的startProcessLocked,這個方法會先判斷是否已經存在相應的進程,如果不存在則通過遠程調用Zygote進程來孵化出新的應用進程,Zygote進程孵化出新的應用進程后,會執行ActivityThread類的main方法。在該方法里會先準備好Looper和消息隊列,然后調用attach方法將應用進程綁定到ActivityManagerService,然后進入loop循環,不斷地讀取消息隊列里的消息,并分發消息。這個過程在Android的消息機制里已經非常熟悉了。其中attach方法在與AMS綁定的過程中會調用attachApplicationLocked方法。attachApplicationLocked方法有兩個重要的函數調用thread.bindApplication和mMainStack.realStartActivityLocked。thread.bindApplication將應用進程的ApplicationThread對象綁定到ActivityManagerService,也就是說獲得ApplicationThread對象的代理對象。mMainStack.realStartActivityLocked通知應用進程啟動Activity。

然后啟動Activity的代碼邏輯來到了realStartActivityLocked。

ActivityStack#realStartActivityLocked

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { //... try { //... app.thread.scheduleLaunchActivity(new Intent(r.intent), r.aPPToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, r.icicle, results, newIntents, !andResume, mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop); //... } catch (RemoteException e) { //... } //... return true;}

app.thread其實就是ApplicationThread在AMS的代理對象,實際上是調用ApplicationThread#scheduleLaunchActivity。接下來Activity的啟動工作就交給應用進程來完成了,別忘了這時候的Activity對象還沒被創建呢。

ActivityThread當家做主

ApplicationThread接收到來自AMS的Activity啟動命令后,將啟動消息通過H(extends Handler)對象發給ActivityThread。

handleLauchActivity方法中包含了ActivityThread中啟動Activity的幾乎全部邏輯,這個方法內會調用兩個重要的方法:performLaunchActivity和handleResumeActivity。

ActivityThread#performLaunchActivity

performLaunchActivity方法內完成了如下工作:

通過類加載器加載Activity對象創建ContextImpl對象并調用activity的attach方法,把上下文變量設置進activity中,創建Window對象和設置WindowManager。回調onCreate,onStart和onRestoreInstanceState方法。

ActivityThread#handleResumeActivity

handleResumeActivity方法內完成了如下工作:

回調Activity的onResume方法調用WindowManager的addView方法,將前面在attach方法內創建出來的window對象添加到WindowManager當中。

關于setContentView:

通常setContentView會在Activity的onCreate方法中調用。但必須要在onCreate中調用嗎?其實setContentView完成了DecorView的創建和繪制,只要在調用WindowManager#addView之前調用setContentView方法也是OK的。因此,最遲到onResume方法中調用setContentView也是可以的。

完整的時序圖

startActivity時序圖 完整圖片

相關源碼:

https://github.com/android/platform_frameworks_base/blob/master/core/java/android/app/ActivityThread.javahttps://github.com/android/platform_frameworks_base/blob/master/services/core/java/com/android/server/am/ActivityManagerService.javahttps://github.com/android/platform_frameworks_base/blob/master/services/core/java/com/android/server/am/ActivityManagerService.javahttps://github.com/android/platform_frameworks_base/blob/master/services/core/java/com/android/server/am/ActivityStarter.javahttps://github.com/android/platform_frameworks_base/blob/master/services/core/java/com/android/server/am/ActivityStackSupervisor.javahttps://github.com/android/platform_frameworks_base/blob/master/services/core/java/com/android/server/am/ActivityStack.java

站在大佬的肩膀上

《Android開發藝術探索》 Android應用程序內部啟動Activity過程(startActivity)的源代碼分析

Android應用程序啟動過程源代碼分析

Android應用程序的Activity啟動過程簡要介紹和學習計劃

深入理解Activity啟動流程(一)–Activity啟動的概要流程 深入理解Activity啟動流程(二)–Activity啟動相關類的類圖 深入理解Activity啟動流程(三)–Activity啟動的詳細流程1 深入理解Activity啟動流程(三)–Activity啟動的詳細流程2

startActivity啟動過程分析


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 资兴市| 庆阳市| 金阳县| 龙川县| 罗平县| 宣化县| 牟定县| 章丘市| 聂荣县| 新和县| 精河县| 正蓝旗| 承德市| 黄大仙区| 壶关县| 饶阳县| 聂荣县| 阜阳市| 彰化市| 通道| 祁连县| 樟树市| 云龙县| 凤山市| 游戏| 介休市| 麻阳| 承德市| 得荣县| 平原县| 津市市| 海伦市| 杭锦旗| 乾安县| 页游| 淮阳县| 姚安县| 普格县| 体育| 鹿泉市| 姚安县|