相關文章
Android深刻四大組件系列
Android系統啓動系列html
Android應用程序進程系列
Android深刻解析AMS系列java
在幾個月前我寫了Android深刻四大組件(一)應用程序啓動過程(前篇)和Android深刻四大組件(一)應用程序啓動過程(後篇)這兩篇文章,它們都是基於Android 7.0,當我開始閱讀Android 8.0源碼時發現應用程序(根Activity)啓動過程照Android 7.0有了一些變化,所以又寫下了本篇文章,本篇文章照此前的文章不只流程發生變化,並且增長了一些分析,算是升級版本。因爲篇幅較長,Android8.0 根Activity啓動過程仍舊分爲前篇和後篇來進行講解。android
經過前篇的介紹,咱們知道目前的代碼邏輯運行在應用程序進程中。先來查看ActivityThread啓動Activity的過程的時序圖。 app
咱們接着來查看ApplicationThread的scheduleLaunchActivity方法,其中ApplicationThread是ActivityThread的內部類,應用程序進程建立後會運行表明主線程的實例ActivityThread,它管理着當前應用程序進程的線程。ApplicationThread的scheduleLaunchActivity方法以下所示。async
frameworks/base/core/java/android/app/ActivityThread.javaide
@Override
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);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.referrer = referrer;
...
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
複製代碼
scheduleLaunchActivity方法會將啓動Activity的參數封裝成ActivityClientRecord ,sendMessage方法向H類發送類型爲LAUNCH_ACTIVITY的消息,並將ActivityClientRecord 傳遞過去,sendMessage方法有多個重載方法,最終調用的sendMessage方法以下所示。 frameworks/base/core/java/android/app/ActivityThread.javapost
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES) Slog.v(
TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
+ ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
複製代碼
這裏mH指的是H,它是ActivityThread的內部類並繼承Handler,是應用程序進程中主線程的消息管理類。H的代碼以下所示。學習
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
...
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;//1
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);//2
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//3
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
複製代碼
查看H的handleMessage方法中對LAUNCH_ACTIVITY的處理,在註釋1處將傳過來的msg的成員變量obj轉換爲ActivityClientRecord。 在註釋2處經過getPackageInfoNoCheck方法得到LoadedApk類型的對象並賦值給ActivityClientRecord 的成員變量packageInfo 。應用程序進程要啓動Activity時須要將該Activity所屬的APK加載進來,而LoadedApk就是用來描述已加載的APK文件。 在註釋3處調用handleLaunchActivity方法,代碼以下所示。 frameworks/base/core/java/android/app/ActivityThread.javathis
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
WindowManagerGlobal.initialize();
//啓動Activity
Activity a = performLaunchActivity(r, customIntent);//1
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
//將Activity的狀態置爲Resume
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);//2
if (!r.activity.mFinished && r.startsNotResumed) {
performPauseActivityIfNeeded(r, reason);
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
try {
//中止Activity啓動
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
複製代碼
註釋1處的performLaunchActivity方法用來啓動Activity ,註釋2處的代碼用來將Activity 的狀態置爲Resume。若是該Activity爲null則會通知AMS中止啓動Activity。來查看performLaunchActivity方法作了什麼: frameworks/base/core/java/android/app/ActivityThread.javaspa
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
//獲取ActivityInfo類
ActivityInfo aInfo = r.activityInfo;//1
if (r.packageInfo == null) {
//獲取APK文件的描述類LoadedApk
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);//2
}
ComponentName component = r.intent.getComponent();//3
...
//建立要啓動Activity的上下文環境
ContextImpl appContext = createBaseContextForActivity(r);//4
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
//用類加載器來建立該Activity的實例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);//5
...
} catch (Exception e) {
...
}
try {
//建立Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);//6
...
if (activity != null) {
...
/** *7 初始化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, r.configCallback);
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);//8
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
複製代碼
註釋1處用來獲取ActivityInfo,ActivityInfo用於存儲代碼和AndroidManifes設置的Activity和receiver節點信息,好比Activity的theme和launchMode。在註釋2處獲取APK文件的描述類LoadedApk。註釋3處獲取要啓動的Activity的ComponentName類,ComponentName類中保存了該Activity的包名和類名。註釋4處用來建立要啓動Activity的上下文環境。註釋5處根據ComponentName中存儲的Activity類名,用類加載器來建立該Activity的實例。註釋6處用來建立Application,makeApplication方法內部會調用Application的onCreate方法。註釋7處調用Activity的attach方法初始化Activity,attach方法中會建立Window對象(PhoneWindow)並與Activity自身進行關聯。註釋8處會調用Instrumentation的callActivityOnCreate方法來啓動Activity,以下所示。 frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);//1
postPerformCreate(activity);
}
複製代碼
註釋1處調用了Activity的performCreate方法,代碼以下所示。 frameworks/base/core/java/android/app/Activity.java
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
複製代碼
performCreate方法中會調用Activity的onCreate方法,講到這裏,根Activity就啓動了,即應用程序就啓動了。 根Activity啓動過程就講到這裏,下面咱們來學習根Activity啓動過程當中涉及到的進程。
在應用程序進程沒有建立的狀況下,根Activity啓動過程當中會涉及到4個進程,分別是Zygote進程、Launcher進程、AMS所在進程(SyetemServer進程)、應用程序進程。它們之間的關係以下圖所示。
首先Launcher進程向AMS請求建立根Activity,AMS會判斷根Activity所需的應用程序進程是否存在並啓動,若是不存在就會請求Zygote進程建立應用程序進程。應用程序進程準備就緒後會通知AMS,AMS會請求應用程序進程建立根Activity。關於上圖中四個步驟的進程間通訊方式,其中步驟2和步驟3相關的進程採用的是Socket通訊,步驟1和步驟4相關的進程採用的Binder通訊。 上圖可能並非很直觀,爲了更好的理解,下面給出這四個進程調用的時序圖。
若是是普通Activity啓動過程會涉及到幾個進程呢?答案是兩個,AMS所在進程和應用程序進程。實際上理解了根Activity的啓動過程(根Activity的onCreate過程),根Activity和普通Activity其餘生命週期狀態好比onStart、onResume等過程也會很輕鬆的掌握,這些知識點都是舉一反三的,想要具體瞭解這些知識點的同窗能夠自行閱讀源碼。