Activity 的冷熱啟動(dòng)
Activity的啟動(dòng)分為冷和熱啟動(dòng)兩種浩聋,所謂的冷啟動(dòng)指的是當(dāng)前進(jìn)程不在的時(shí)候瘦麸,啟動(dòng)一個(gè)activity。就相當(dāng)于我們?cè)趌auncher 桌面上點(diǎn)擊某一個(gè)app的圖標(biāo)啟動(dòng)一個(gè)應(yīng)用,并且跳轉(zhuǎn)到對(duì)應(yīng)的activity(通常是MainActivity或者SplashActivity)的流程,launcher其實(shí)也是一個(gè)應(yīng)用進(jìn)程多糠。所謂的熱啟動(dòng)指的就是在應(yīng)用內(nèi)一個(gè)ActivityA跳轉(zhuǎn)到ActivityB的流程累舷。這個(gè)流程比冷啟動(dòng)簡(jiǎn)單的多浩考,這個(gè)過(guò)程我們更關(guān)注當(dāng)前兩個(gè)Activity的生命周期的調(diào)用,這個(gè)流程不是本文的分析重點(diǎn)
時(shí)序圖分析
在分析之前被盈,先奉獻(xiàn)上我自己畫的一張activity啟動(dòng)流程的時(shí)序圖在這張時(shí)序圖里面我們可以看到析孽,完成啟動(dòng)一個(gè)activity可能需要用到的類有
1 ActivityThread
2 ActivityManagerService
3 Zygote
4 Activity
如果當(dāng)前應(yīng)用處于熱啟動(dòng)狀態(tài),那么Android系統(tǒng)就不需要Zygote的介入只怎,但是當(dāng)我們應(yīng)用處于冷啟動(dòng)流程袜瞬,也即是從桌面上點(diǎn)擊了應(yīng)用的icon圖標(biāo)進(jìn)入的流程,就需要Zygote了來(lái)幫我們把目標(biāo)進(jìn)程fork出來(lái)了身堡。具體的話我們看下面的源碼分析邓尤。
Activity 啟動(dòng)流程分析
startActivity開始
Intent intent=new Intent();
startActivity(intent);
我們一步一步往里面跟,其實(shí)startActivity方法最后調(diào)用的是startActivityForResult()的方法贴谎。我們來(lái)看一下startActivityForResult的源碼
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
這里我們可以看到兩個(gè)重要的分支汞扎,如果當(dāng)前的mParent不存在的時(shí)候,那么就調(diào)用
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
這里的instrumentation的execstartActivity就是調(diào)用到了ActivityManagerService 的startActivity方法擅这。經(jīng)過(guò)一系列轉(zhuǎn)換后澈魄,會(huì)調(diào)用startProcessLocked方法,這里就開始會(huì)和zygote交互了
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
我們這里進(jìn)入到process.start()方法
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
在這里startViaZygote會(huì)通過(guò)socket的方法仲翎,把Zygote喚醒(我們?cè)谶@里需要關(guān)注的socket-connect 關(guān)鍵字往前追蹤)
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv, classLoader);
}
最終的調(diào)用方法就是我們的時(shí)序圖中看到的invokeStaticMain方法痹扇,它會(huì)根據(jù)我們?cè)谥皳饺氲膃ntrypoint,把ActivityThread的main方法調(diào)用起來(lái)溯香。這里我們就進(jìn)入到第三個(gè)關(guān)鍵的類ActivityThread
ActivityThread做了什么
我們首先進(jìn)入ActivityThread的main方法
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
里面最重要的方法已經(jīng)展現(xiàn)出來(lái)了鲫构,就是attach方法。我們繼續(xù)進(jìn)入attach方法
里面最重要的調(diào)用就是
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
這個(gè)時(shí)候又回到ActivityManagerService里面了玫坛。
ActivityManagerService經(jīng)過(guò)一系列的調(diào)用后结笨,就繼續(xù)調(diào)用到ActivityThread里面的bindApplication中了。
ActivityThread的bindApplication主要就是把當(dāng)前的上下文和application綁定起來(lái)。
app 的如何被創(chuàng)建
ActivityThread 里面的handleBindApplication方法就是目標(biāo)應(yīng)用啟動(dòng)的入口禀梳。這個(gè)方法是在前面的bindApplication通過(guò)handler通訊的方法觸發(fā)調(diào)用的杜窄,我們主要關(guān)注handleBindApplication里面的這一句:
mInstrumentation.callApplicationOnCreate(app);
這一個(gè)方法就把a(bǔ)pplication onCreate() 給創(chuàng)建起來(lái)了。
Activity 如何被啟動(dòng)
Activity真正啟動(dòng)的入口在ActivityThread 里面的scheduleLaunchActivity方法中算途。這個(gè)方法同樣也是有ActivityManagerService觸發(fā)塞耕。我們進(jìn)入ScheduleLaunchActivity中可以看到核心的方法調(diào)用的是
sendMessage(H.LAUNCH_ACTIVITY, r);
同樣是通過(guò)handler,把當(dāng)前l(fā)auncher_activity的指令發(fā)送出去嘴瓤。最后會(huì)走到
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
// Initialize before creating the activity
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
if (!r.activity.mFinished && r.startsNotResumed) {
// The activity manager actually wants this one to start out paused, because it
// needs to be visible but isn't in the foreground. We accomplish this by going
// through the normal startup (because activities expect to go through onResume()
// the first time they run, before their window is displayed), and then pausing it.
// However, in this case we do -not- need to do the full pause cycle (of freezing
// and such) because the activity manager assumes it can just retain the current
// state it has.
performPauseActivityIfNeeded(r, reason);
// We need to keep around the original state, in case we need to be created again.
// But we only do this for pre-Honeycomb apps, which always save their state when
// pausing, so we can not have them save their state when restarting from a paused
// state. For HC and later, we want to (and can) let the state be saved as the
// normal part of stopping the activity.
if (r.isPreHoneycomb()) {
r.state = oldState;
}
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
這里面就是兩個(gè)重要的流程了:
Activity a = performLaunchActivity(r, customIntent);
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
對(duì)應(yīng)的就是我們activity的生命周期了
總結(jié)
由于activity啟動(dòng)流程里面扫外,比較復(fù)雜的就是應(yīng)用的冷啟動(dòng)的流程,一套代碼流程下來(lái)就是非常的繁瑣廓脆。特別是在最新的Android9以上筛谚,出現(xiàn)了很多的handler和socket通訊的方法調(diào)用,如果代碼不是很熟悉的話停忿,查找整個(gè)調(diào)用棧會(huì)非常的有挑戰(zhàn)性驾讲。這里還是希望大家可以仔細(xì)的查看代碼,follow一下流程席赂,相信大家都會(huì)有不錯(cuò)的收獲和體驗(yàn)