Activity啟動流程原始碼實作(七)初始化目標Activity并執行相關生命周期流程
Android四大組件原始碼實作詳解系列博客目錄:
Android應用行程創建流程大揭秘
Android四大組件之bindService原始碼實作詳解
Android四大組件之Activity啟動流程原始碼實作詳解概要
Android四大組件之Activity啟動流程原始碼實作詳解(一)
Android四大組件之Activity啟動流程原始碼實作詳解(二)
Activity啟動流程(三)- Activity Task調度演算法復盤分析
Activity啟動流程(四)- Pause前臺顯示Activity,Resume目標Activity
Activity啟動流程(五)- 請求并創建目標Activity行程
Activity啟動流程(六)- 注冊目標Activity行程到system_server行程以及創建目標Activity行程Application
Activity啟動流程(七)- 初始化目標Activity并執行相關生命周期流程
前言
??不知不覺Activity啟動系列博客已經更新到系列七來了,這其中的不容易和艱辛只有自己知道了,前面的幾章主要是重點分析了Activity啟動程序中的涉及的前兩個階段請求階段和行程創建階段,上述兩個階段成果為我們的Activity的啟動和顯示構建好了穩定的外部環境和載體,但是革命尚未成功同志仍需努力啊!在這一篇章中我們將重點介紹Android是怎么開啟目標Activity生命周期如下小階段的:
- 真正啟動目的端Activity
- 通過反射加載目標Activity
- 執行目標Activity生命周期
- 初始化目標Activity視窗為顯示做準備
注意:本篇的介紹是基于Android 7.xx平臺為基礎的,其中涉及的代碼路徑如下:
frameworks/base/services/core/java/com/android/server/am/
--- ActivityManagerService.java
--- ProcessRecord.java
--- ActivityRecord.java
--- ActivityResult.java
--- ActivityStack.java
--- ActivityStackSupervisor.java
--- ActivityStarter.java
--- TaskRecord.java
frameworks/base/services/core/java/com/android/server/pm/
--- PackageManagerService.java
frameworks/base/core/java/android/content/pm/
--- ActivityInfo.java
frameworks/base/core/java/android/app/
--- IActivityManager.java
--- ActivityManagerNative.java (內部包含AMP)
--- ActivityManager.java
--- AppGlobals.java
--- Activity.java
--- ActivityThread.java(內含AT)
--- LoadedApk.java
--- AppGlobals.java
--- Application.java
--- Instrumentation.java
--- IApplicationThread.java
--- ApplicationThreadNative.java (內部包含ATP)
--- ActivityThread.java (內含ApplicationThread)
--- ContextImpl.java
并且在后續的原始碼分析程序中為了簡述方便,會將做如下簡述:
- ApplicationThreadProxy簡稱為ATP
- ActivityManagerProxy簡稱為AMP
- ActivityManagerService簡稱為AMS
- ActivityManagerNative簡稱AMN
- ApplicationThreadNative簡稱ATN
- PackageManagerService簡稱為PKMS
- ApplicationThread簡稱為AT
- ActivityStarter簡稱為AS,這里不要和ActivityServices搞混淆了
- ActivityStackSupervisor簡稱為ASS
在正式開始今天博客相關原始碼分析前,還是先奉上今天博客將要涉及到的時序圖以便小伙們先從整體上有個清晰的概括,然后再從細節開擼!

我們對上述的時序圖簡單的來注釋一下:
綠色的組件表示的是運行在目標Activity所屬行程中
藍色的組件表示是運行在system_server行程中
Activity所屬行程和system_server行程之間通過紅色箭頭表示的Binder完成了跨行程通信,配合完成了Activity啟動的下半場接力賽
紫色箭頭表示的是Handler內部資訊傳遞
一. system_server行程真正的啟動目標Activity
??看到這個標題也許有小伙們心里想了,難不成我們搞了這么久前面的博客都是假啟動目標Activity了,這個當然不是了!怎么說呢,打個不恰當的比喻啊,這個就好像你找女朋友,找老婆必須有個前期儲備建立感情基礎不,而我們前面所做的就是為了此時真正的啟動目標Activity打下的夯實基礎而已!
好了,我們繼續回到前面博客Activity啟動流程(六)- 注冊目標Activity行程到system_server行程以及創建目標Activity行程Application的章節1.3,在我們的目標Actiivty應用行程起來之后,會繼續檢查有沒有四大組件在等待運行,如果有會繼續其運行(這里我么只關注Activity的啟動),
1.1 ASS.attachApplicationLocked(…)
??尼瑪!這里又是一個attachApplicationLocked方法,是不是搞錯了,真沒有錯!最外層的attachApplicationLocked是針對AMS的,而這里的attachApplicationLocked方法是針對ASS的,
該方法取名為attachApplication(),顧名思義就是給ASS系結一個應用,那么,ASS中有什么需要被系結到一個應用行程的呢?如果小伙們是從Actiivity啟動的請求階段一路走過來那就知道當然是AcivityRecord了,我們在啟動目標Activity時創建或者復用了一個新的ActivityRecord,并將其挪到了Stack的堆疊頂位置,當時,ActivityRecord還沒有關聯到任何行程相關的資訊,還不能被遷移到顯示狀態,當應用行程被創建之后,Activity才有了運行的機會,這時候才會真正調度我們前面的ActivityRecord,
//[ActivityStackSupervisor.java]
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
/*
獲取堆疊定的ActivityRecord
此時經過Activity請求階段一系列的作業,已經把Activity所屬的Task和ActivityStack移動到頂了
*/
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
//詳見章節1.2
if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (RemoteException e) {
...
}
}
}
}
}
return didSomething;
}
該方法的實作邏輯與我們前面博客中介紹的ASS的其他方法基本類似:
- 遍歷尋找所有ActivityStack和TaskRecord,然后找到目標Activity的ActivityRecord
- 對堆疊頂的目標ActivityRecord進行操作,將上述作為引數繼續呼叫realStartActivityLocked真正啟動目標Activity
這里的realStartActivityLocked是不是有點似曾相識的感覺!是的,在前面博客中Activity啟動流程(五)- 請求并創建目標Activity行程的2.1章節中的startSpecificActivityLocked我們有見過它的身影,并且當時的判斷條件是是如果目標Activity所屬行程已經創建了的話就會直接進入此分支(如果對于此處有所遺忘的小伙們,可以回頭看看),看來它很重要啊,我們來強烈圍觀一下!
1.2 ASS.realStartActivityLocked(…)
??此方法很霸氣啊,真的啟動Activity!感覺有點像我們小時候過年走親戚,快要出門的時候大聲對主人家說,我真的要告辭了啊(意外之意就是主人家,得準備好紅包給我們小孩了)!而這里的弦外之音,我們可以理解我就是要開啟Activity的相關生命周期了,即我們應用開發者所熟知的onCreate()/onStart()等方法的調度,這應該就是這里真正啟動Activity的真正含義嗎!
//[ActivityStackSupervisor.java]
final boolean realStartActivityLocked(ActivityRecord r, //目標Activity資料資訊
ProcessRecord app,//目標Activity所屬行程資訊
boolean andResume, //是否執行resume,傳入的引數值為true
boolean checkConfig)//是否檢查Config配置,傳入的引數值為true
throws RemoteException {
...
r.app = app;
...
int idx = app.activities.indexOf(r);
//判斷當前要啟動的Activty是否在ProcessRecord中有相關的記錄,如若沒有則把它加到ProcessRecord中
if (idx < 0) {
app.activities.add(r);
}
mService.updateLruProcessLocked(app, true, null);//更新行程Lru
mService.updateOomAdjLocked();//更新行程adj優先級
...
/*
此處的套路,小伙們應該見怪不怪了嗎,前面的博客中有多處用到
通過IApplicationThread匿名Binder呼叫到目標Activity行程的ActivityThread中
*/
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);//詳見章節2.1
...
if (andResume) {
/*
此時目標Activity已經呼叫完onResume()方法了,
所以這時候需要將目標Activity所屬的ActivityStack堆疊中的mResumedActivity
設定目標Activity,并且狀態置為RESUMED
*/
stack.minimalResumeActivityLocked(r);
/*************************************************************/
//這里為了方便演示,將上述原始碼就地展開
//[ActivitStack.java]
void minimalResumeActivityLocked(ActivityRecord r) {
r.state = ActivityState.RESUMED;//設定為RESUMED狀態
mResumedActivity = r; //并將ActivityRecord賦給對應的stack的mResumedActivity
...
}
/*************************************************************/
} else {
...
}
...
return true;
}
realStartActivityLocked()方法的邏輯不少,我們這里抽絲剝繭只取一瓢,重點關注如下三點:
- 將目標ActivityRecord和對應的ProcessRecord關聯起來,即通過ActivityRecord可以找到對應的ProcessRecord,然后將目標ActivityRecord存入到ProcessRecord資料結構中的activities串列中!真是你中有我,我中有你的典范啊!
- 借助ATP跨行程呼叫AT中的scheduleLaunchActivity()方法,進而調度啟動目標Activity(這個是重點)
- 目標Activity已經呼叫完onResume()等生命周期流程之后,這時將目標Activity所屬的ActivityStack堆疊中的mResumedActivity設定目標Activity,并且狀態置為RESUMED,為后續的Activity相關調度構建好環境
二. 創建并加載目標Activity
??如上一切執行妥當以后,system_server行程會通過IApplicationThread跨行程回呼到目標Activity應用行程,從而開始驅動目標Actiivity生命周期的運轉和執行了,至于IApplicationThread是怎么實作跨行程呼叫的這里我也不贅述了(這個當然是Binder的功能,分析Android原始碼Binder是一道必須跨過去的坎啊,并且這個呼叫的流程在該系列前面的博客中也有詳細的分析過,這里就不贅述了,看的多了,不理解應該也大概能懂了)!總之通過app.thread.scheduleLaunchActivity實際上呼叫的就是目標Activity行程中ActivityThread的內部類ApplicationThread的scheduleLaunchActivity方法中去了,還是放上一下關于IApplicationThread類圖關系圖嗎(這個冷飯都抄了很多次了)!

其呼叫程序可以使用下面的偽代碼來表示:
ATP.scheduleLaunchActivity()--->
BinderProxy.transact() --->
BpBinder.transact()--->
binder驅動傳輸--->
JavaBBinder.onTransact()--->
ATN.onTransact()--->
ATN.scheduleLaunchActivity(...) --->
ActivityThread.ApplicationThread.scheduleLaunchActivity(...) --->
2.1 ActivityThread.ApplicationThread.scheduleLaunchActivity(…)
//[ActivityThread.java]
private class ApplicationThread extends ApplicationThreadNative {
...
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
int procState, Bundle state, PersistableBundle persistentState,
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
//將AMS傳遞過來啟動目標Activity相關的引數填充ActivityClientRecord 資料結構
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
r.voiceInteractor = voiceInteractor;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.persistentState = persistentState;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profilerInfo = profilerInfo;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
...
}
此時的scheduleLaunchActivity()方法在ApplicationThread的Binder執行緒中執行,在該方法中將AMS傳遞過來的引數填充ActivityClientRecord資料結構,然后通過ActivityThread.H攜帶上述引數呼叫到ActivityThread的主執行緒中執行處理,而處理上述邏輯的即是handleLaunchActivity()方法!
在ActivityThread中有如下的一個套路,通常AMS中通過Binder遠程呼叫的scheduleXXX方法,經過Handler的傳遞以后通常會在主執行緒中的handleXXX進行下一步的處理!
我們接著繼續分析,看看handleLaunchActivity()的處理邏輯!
2.2 ActivityThread.handleLaunchActivity(…)加載并開啟Activity生命周期
前面的一切付出都是值得的,進入此流程就要真正的加載并開啟目標Activity的生命周期了,付出了這么多終于見到了回報和勝利的輸光了!
//[ActivityThread.java]
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
unscheduleGcIdler();//GC相關處理
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
//最侄訓呼目標Activity的onConfigurationChanged()
handleConfigurationChanged(null, null);
//獲取WMS服務代理端
WindowManagerGlobal.initialize();
//加載目標Activity,并最侄訓呼目標Activity的onCreate
Activity a = performLaunchActivity(r, customIntent);//詳見章節2.3
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//最侄訓呼目標Activity的onStart,onResume.
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//詳見章節2.4
if (!r.activity.mFinished && r.startsNotResumed) {//這個正常的啟動目標Activity不會進入此分支
...
}
} else {
//如果啟動目標Activity發生例外則直接finish掉目標Activity
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
}
}
這里handleLaunchActivity()方法處理的邏輯是什么呢,大概可以分為如下幾部分:
- 首先做一些基本的初始化引數設定作業
- 接著呼叫performLaunchActivity()方法加載目標Activity,并最侄訓呼目標Activity的onCreate()等生命周期方法
- 如果上述步驟執行成功,繼續呼叫handleResumeActivity()方法來處理Activity進入顯示狀態時需要完成的操作
- 如果步驟二的操作失敗,則通知AMS將目標Activity直接finish掉
2.3 ActivityThread.performLaunchActivity(…)加載Activity
這個方法是真正的負責執行目標Activity的加載和啟動,是system_server行程負責調度目標Activity啟動的落腳點,從此處開始真正進入我們所熟知的Activity生命周期相關流程!
//[ActivityThread.java]
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//開始構建目標Activity相關資訊
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
Activity activity = null;
try {
/*
通過反射加載目標Activity
這里獲取的ClassLoader是前面博客已經初始化了的
*/
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
/*****************************************************/
//這里為了演示方便,直接把原始碼展開
//[Instrumentation.java]
public Activity newActivity(ClassLoader cl, String className,
Intent intent)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
/*****************************************************/
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
/*
創建目標Actiivty應用行程Application,目標Application在前面博客中已經有被創建了,而且
應用行程的Application是唯一的,所以會直接回傳前面創建的Applcation
*/
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
//創建目標Activity對應的Context背景關系
Context appContext = createBaseContextForActivity(r, activity);
/*****************************************************/
//[ActivityThread.java]
//這里為了演示方便,將其擴展開
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
int displayId = Display.DEFAULT_DISPLAY;
try {
displayId = ActivityManagerNative.getDefault().getActivityDisplayId(r.token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
ContextImpl appContext = ContextImpl.createActivityContext(
this, r.packageInfo, r.token, displayId, r.overrideConfig);
appContext.setOuterContext(activity);
Context baseContext = appContext;
final DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
String pkgName = SystemProperties.get("debug.second-display.pkg");
if (pkgName != null && !pkgName.isEmpty()
&& r.packageInfo.mPackageName.contains(pkgName)) {
for (int id : dm.getDisplayIds()) {
if (id != Display.DEFAULT_DISPLAY) {
Display display =
dm.getCompatibleDisplay(id, appContext.getDisplayAdjustments(id));
baseContext = appContext.createDisplayContext(display);
break;
}
}
}
return baseContext;
}
/*****************************************************/
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
//將上述創建的相關資訊,attach到Activity中為后續Activity顯示運行做準備
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {//如果在AndroidManifest中有配置Activity主題,則設定主題
activity.setTheme(theme);
}
activity.mCalled = false;
//開始執行目標Activity的onCreate()方法回呼
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();//執行目標Activity的onStart()方法
r.stopped = false;
}
...
}
r.paused = true;
//將目標Activity相關資訊,保存到mActivities中
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
我們的performLaunchActivity()方法有干了那些事情,有那些功勞呢,我們來掰持掰持:
-
首先會初始化構建目標Activity相關的一些資訊,此處我們目標Activity的創建是通過反射來構建的,這就需要包名、類名等資訊,而其中的絕大部分資訊已經從系統行程傳遞到應用行程了,還有些部分資訊也都可以通過PackageManager再向系統行程索取;
-
上述相關引數準備完畢OK以后,便可以通過ClassLoader加載到Activity對應的類,通過反射加載
-
接著依次創建目標Activity對應的Application物件,當前條件下并不會創建,因為前面已經有初始化過了Application了,而且Activity應用行程只會對應一個Application
-
接著呼叫createBaseContextForActivity()方法繼續構建目標Activity對應的Context背景關系,這里的Activity的Context和前面我們Application的Context最大的不同在于Application的Context只包含了packageInfo,而Activity的context的還包含了displayInfo,所以當需要將Context用在顯示相關的場合時,請使用Activtiy作為Context,
不知道我上面的表達清楚了沒有!一句話總結就是Application中的Context是不能用來做和UI顯示相關的操作!
-
接著呼叫目標Activity的attach()將前面創建相關的資料結構,傳遞到目標Activity中
-
接著如果在AndroidManifest中有配置了目標Activity主題,則設定相關主題,否則使用默認的
-
接著呼叫callActivityOnCreate()方法,進而開始執行目標Activity物件的onCreate方法,至此Actiivty進入其生命周期的開始
-
接著呼叫performStart(),開始目標Activity生命周期的另一征程onStart()方法
分析至此,小伙們是否有一種酣暢淋漓的冠絕,經過了千辛萬苦,總算到Activity.onCreate()這個方法啊!原來我們在應該用開發中的簡簡單單的幾行代碼,在Android系統中是經過了這樣一番曲折的程序才會被執行!
Activity生命周期相關方法就像是Activity調度程序的冰山一角,對于做應用層的開發人員而言,只需要看到最外層的冰山,就能栩栩如生地把冰山的樣子轉述出來;然而,意想不到的是,冰山底下宏大的世界,撐起整座冰山的根基卻是如此的復雜,為了冰山一角我們的谷歌的哥哥姐姐可沒有少做作業啊!
2.4 ActivityThread.handleResumeActivity(…)執行目標Activity的onResume
前面相關的方法執行成功以后,我們的目標Activity物件也已經構建成功,并成功執行完onCreate(), onStart()兩個生命周期的調度之后,便進入到這個階段,執行目標Activity的onResume()生命周期的調度!
//[ActivityThread.java]
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume) {
ActivityClientRecord r = mActivities.get(token);
unscheduleGcIdler();
mSomeActivitiesChanged = true;
// 實際執行應用行程一側的Activity.onResume()
r = performResumeActivity(token, clearHide);
if (r != null) {
... // 省略與WindownManager相關的視窗操作
if (reallyResume) {
// 通知系統行程,Activity已經處于Resumed狀態
ActivityManagerNative.getDefault().activityResumed(token);
}
}
}
這里真正呼叫目標Activity生命周期的onResume()方法的是performResumeActivity()方法,在這里就不展開分析了,至此我們的整個的Actiivty啟動流程到此就結束了!
三. Application/LoadedApk/ContextImpl/Activity關系小結
分析到這里,Activity啟動程序中目標Activity應用行程端涉及的相關幾個重要角色幾乎都已經隆重登場了,特別是Application,LoadedApk,ContextImpl,Activity,而且在前面博客和本篇的博客中都有重點介紹上述幾個概念,這里我們有必要梳理梳理這幾者之間的關系,其幾者之間關系是剪不斷理還亂,但是大致上關系如下:

- Application:在一個App應用行程中是有且唯一的,整個應用行程只有一個實體,它和Activity對應的關系是一對多,通常我們在應用程式開發程序中,當我們重寫了Application類后,應用程式加載運行的是我們定義的Application類,否則就加載運行默認的Application類,Application擁有自己對應的ContextImpl,它擁有的ContextImpl和Activity對應的ContextImpl的區別就是Application物件所擁有的ContextImpl背景關系沒有對應的Token和相關顯示的displayId,所以Application對應的Applcation不能用于UI相關的顯示(Toast除外),否則會拋出如下例外!

-
ContextImpl:這個我們在前面有重點介紹分析過,每個啟動的Activity都擁有屬于自身的ContextImpl物件,并且Application也擁有自己對應的!ContextImpl記錄了應用程式的包名資訊、應用程式的資源資訊、應用程式的主執行緒、ContentResolver及Activity對應的IApplicationToken.Proxy,但是Application物件所擁有的ContextImpl背景關系就沒有對應的Token了!
-
LoadedApk:從我們前面的分析可知LoadedApk類記錄了Activity運行所在的ActivityThread、Activity所在的應用程式資訊、Activity所在應用行程的包名、Activity所在應用行程的資源路徑、Activity應用行程的庫路徑、Activity所在應用行程的資料存盤路徑、類加載器和應用程式所使用的資源等資訊,并且在一個App應用行程中通常是有且唯一的!
-
Activity:它就不需要我過多介紹了,通常學習Android開發的小伙們最先認識的就是它了,它是我們Android世界的顏值擔當,負責界面的呈現!它和ContextImpl是一對一的關系的,每個Activity都擁有自己的ContextImpl!
如上就是幾者之間的牽扯關系了,這個大伙在分析原始碼的時候可以重點關注關注,并且它們之間牽涉了很多的相互參考,理解好了上述的關系對我們理解原始碼大有裨益!
總結
??到此,目標Activity便正式啟動,開始進入Activity生命周期,執行完onCreate/onStart/onResume方法,然后開始UI渲染,經過上述一番操作之后目標Activity就可以顯示到我們的主界面了!
而到此,我們的Android四大組件之Activity啟動流程也就就此完結了!在最后我們從行程的互動角度出發,對我們整個Activity啟動流程簡單總結一番!在總結之前我們先看它涉及的整體流程圖:

目標Actiivyt啟動流程如下:
- 發起端行程(可能是第三方App行程也可能是桌面Launcher)呼叫Binder IPC跨行程通信機制向system_server行程發起startActivity目標Activity請求
- system_server行程在收到發起端行程的請求之后,會做一系列處理為目標Actiivity找到/創建合適的stack和TaskRecord堆疊,創建目標Actiivty對應的ActivityRecord資訊,并且pause前臺顯示的相關Actiivity
- 我們這里的前提是目標Actiivyt應用行程還沒有創建,所以此時system_server行程在處理完上述一切之后,向zygote行程發出請求fork目標Actiivyt行程
- 目標Actiivyt行程被創建之后,通過Binder IPC向sytem_server行程發起attachApplication請求,繼續向AMS注冊相關資料結構為后續目標Activity行程轉變成應用開發所熟知的App行程做相關準備
- 接著system_server行程通過Binder IPC向目標Activity行程發起bindApplication請求
- 目標Actiivyt行程的binder執行緒(ApplicationThread)在收到請求后,通過handler向主執行緒發送BIND_APPLICATION訊息
- 主執行緒在收到Message后,通過發射機制創建目標Application,并回呼Application.onCreate()等方法
- 上述執行OK以后,system_server行程會繼續檢查目標Activity行程是否還有Actiivyt待啟動(當然有了),接著再通過binder IPC向目標Actiivyt行程發送scheduleLaunchActivity請求;
- 目標Activity行程的binder執行緒(ApplicationThread)在收到請求后,通過handler向主執行緒發送LAUNCH_ACTIVITY訊息
- 主執行緒在收到Message后,通過發射機制創建目標Activity,并回呼Activity.onCreate()等方法
寫在最后
??Activity啟動流程(七)- 初始化目標Activity并執行相關生命周期流程這里就要告一段落了,整個的Activity的啟動也基本宣告完結了!雖然說是基本完結了,但是Activiyt啟動程序中涉及的很多知識點并不是到此就已經over了,這個就需要各位小伙們在平時的積累和總結了,在接下來的博客中,我將會重點分析目標Activity的是怎么加載布局以及怎么將布局繪制到我們的終端界面上面的,如果有感興趣的親請期待,好了,青山不改綠水長流先到這里了,如果本博客對你有所幫助,麻煩關注或者點個贊,如果覺得很爛也可以踩一腳!謝謝各位了!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/204030.html
標籤:其他
