淺析Android Activity的啟動過程
Activity作為Android的四大元件之一,也是最基本的元件,負責與使用者互動的所有功能。Activity的啟動過程也並非一件神祕的事情,接下來就簡單的從原始碼的角度分析一下Activity的啟動過程。
根Activity一般就是指我們專案中的MainActivity,代表了一個Android應用程式,一般也是在一個新的程式中啟動起來。在Android系統中,所有的Activity元件都儲存在堆疊中,我們啟動一個新的Activity元件就位於上一個Activity的上面。那麼我們從桌面(Launcher)開啟一個App是一個怎樣的過程呢,如下所示:
(1)Launcher向ActivityManagerService傳送一個啟動MainActivity的請求;
(2)ActivityManagerService首先將MainActivity的相關資訊儲存下來,然後向Launcher傳送一個使之進入中止狀態的請求;
(3)Launcher收到中止狀態之後,就會想ActivityManagerService傳送一個已進入中止狀態的請求,便於ActivityManagerService繼續執行啟動MainActivity的操作;
(4)ActivityManagerService檢查用於執行MainActivity的程式,如果不存在,則啟動一個新的程式;
(5)新的應用程式程式啟動完成之後,就會向ActivityManagerService傳送一個啟動完成的請求,便於ActivityManagerService繼續執行啟動MainActivity的操作;
(6)ActivityManagerService將第(2)步儲存下來的MainActivity相關資訊傳送給新建立的程式,便於該程式啟動MainActivity元件。
Launcher.startActivitySafely
boolean startActivitySafely(Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
return true;
} catch (ActivityNotFoundException e) {}
}
當我們在Launcher上點選應用程式圖示時,startActivitySafely方法會被呼叫。需要啟動的Activity資訊儲存在intent中,包括action、category等等。那麼Launcher是如何獲得intent裡面的這些資訊呢?首先,系統在啟動時會啟動一個叫做PackageManagerService的管理服務,並且通過他來安裝系統中的應用程式,在這個過程中,PackageManagerService會對應用程式的配置檔案AndroidManifest.xml進行解析,從而得到程式裡的元件資訊(包括Activity、Service、Broadcast等),然後PackageManagerService去查詢所有action為“android.intent.action.MAIN”並且category為“android.intent.category.LAUNCHER”的Activity,然後為每個應用程式建立一個快捷方式圖示,並把程式資訊與之關聯。上述程式碼中,Activity的啟動標誌位設定為“Intent.FLAG_ACTIVITY_NEW_TASK”,便於他可以在一個新的任務中啟動。
Activity.startActivity
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
呼叫startActivityForResult,第二個引數(requestCode)為-1則表示在Activity關閉時不需要將結果傳回來。Activity.startActivityForResult
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) { //一般的Activity其mParent都為null
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this,
mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
if (ar != null) { //傳送結果,即onActivityResult會被呼叫
mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
final View decor = mWindow != null ? mWindow.peekDecorView() : null;
if (decor != null) {
decor.cancelPendingInputEvents();
}
} else { //在ActivityGroup內部的Activity,內部處理邏輯和上面是類似的
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
if (options != null && !isTopOfTask()) {
mActivityTransitionState.startExitOutTransition(this, options);
}
}
不難發現,最後實際上是呼叫mInstrumentation.execStartActivity來啟動Activity,mInstrumentation型別為Instrumentation,用於監控程式和系統之間的互動操作。mInstrumentation代為執行Activity的啟動操作,便於他可以監控這一個互動過程。mMainThread的型別為ActivityThread,用於描述一個應用程式程式,系統每啟動一個程式都會在它裡面載入一個ActivityThread的例項,並且將該例項儲存在Activity的成員變數mMainThread中,而mMainThread.getApplicationThread()則用於獲取其內部一個型別為ApplicationThread的本地Binder物件。mToken的型別為IBinder,他是一個Binder的代理物件,只想了ActivityManagerService中一個型別為ActivityRecord的本地Binder物件。每一個已經啟動的Activity在ActivityManagerService中都有一個對應的ActivityRecord物件,用於維護Activity的執行狀態及資訊。
Instrumentation.execStartActivity
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) { //先查詢一遍看是否存在這個activity
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault().startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options); //這裡才是真正開啟activity的地方,其核心功能在whoThread中完成。
checkStartActivityResult(result, intent); // 處理各種異常,如ActivityNotFound
} catch (RemoteException e) {
}
return null;
}
上述程式碼可知,通過ActivityManagerNative.getDefault()獲取一個ActivityManagerService的代理物件,然後呼叫他的startActivity方法來通知ActivityManagerService去啟動Activity。中間還有一系列過程,跟著原始碼走下去,不難發現,最後,是呼叫ApplicationThread的scheduleLaunchActivity來進行Activity的啟動。
Application.scheduleLaunchActivity
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, 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;
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;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
上述程式碼主要做的事就是構造一個ActivityClientRecord,然後呼叫sendMessage傳送一個訊息。在應用程式對應的程式中,每一個Activity元件都使用一個ActivityClientRecord物件來描述,他們儲存在ActivityThread類的成員變數mActivities中。那麼Handler是如何處理這個訊息的呢?
H.handleMessage
switch (msg.what) { // 訊息型別
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null); // 處理訊息
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;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
(msg.arg1&2) != 0);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
... ...
}
首先將msg裡面的obj轉成一個ActivityClientRecord物件,然後呼叫來獲取一個LoaderApk物件並儲存在ActivityClientRecord物件的成員變數packageInfo中。Loader物件用於描述一個已經載入的APK檔案。最後呼叫handleLaunchActivity來啟動Activity元件。
ActivityThread.handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
handleConfigurationChanged(null, null);
if (localLOGV) Slog.v(
TAG, "Handling launch of " + r);
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent); //performLaunchActivity真正完成了activity的調起,Activity被例項化,onCreate被呼叫
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward, // 再呼叫Activity例項的Resume(使用者介面可見)
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity); // finish的時候先調onPause
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to pause activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.paused = true;
}
} else {
try {
ActivityManagerNative.getDefault() // finishActivity 一樣的原理
.finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
} catch (RemoteException ex) {
}
}
}
到了這一步,那就很清晰了。憋了一口氣到這裡,是不是突然放鬆了一下~~ 再來看看performLaunchActivity做的事兒~~performLaunchActivity函式載入使用者自定義的Activity的派生類,並執行其onCreate函式,它將返回此Activity物件。ActivityThread.performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//從intent中取出目標activity的啟動引數(包名、類名等)
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 {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); // 將Activity類檔案載入到記憶體中
activity = mInstrumentation.newActivity( // 建立Activity例項
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
if (localLOGV) Slog.v(
TAG, r + ": app=" + app
+ ", appName=" + app.getPackageName()
+ ", pkg=" + r.packageInfo.getPackageName()
+ ", comp=" + r.intent.getComponent().toShortString()
+ ", dir=" + r.packageInfo.getAppDir());
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity); // 初始化Context物件,作為Activity的上下文
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
+ r.activityInfo.name + " with config " + config);
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) { //下面就是呼叫到acitivity的onCreate方法了
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
} // 至此,Activity啟動過程就結束了,其生命週期由ApplicationThread來管理
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();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r); // 將ActivityRecord物件儲存在ActivityThread的mActivities中
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
ActivityRecord裡面的token,是一個Binder的代理物件,和ActivityClientRecord物件一樣,都是用來描述所啟動的Activity元件,只不過前者是在ActivityManagerService中使用,後者是在應用程式程式中使用。
至此,Activity的啟動過程就分析完了。MainActivity的啟動過程,其實也可以認為是應用程式的啟動過程。
子Activity的啟動過程和根Activity的啟動過程也是類似的,過程如下:
(1)MainActivity向ActivityManagerService傳送一個自動ChildActivity的請求;
(2)ActivityManagerService首先將ChildActivity的資訊儲存下來,再向MainActivity傳送一箇中止的請求;
(3)MainActivity收到請求進入中止狀態,告訴ActivityManagerService,便於ActivityManagerService繼續執行啟動ChildActivity的操作
(4)ActivityManagerService檢查ChildActivity所執行的程式是否存在,存在就傳送ChildActivity資訊給他,以進行啟動。
原始碼方面,原理類似,相比起來會比MainActivity的稍微簡單一些,這裡就不再詳細敘述了,各位可以自行根據前面步驟,閱讀原始碼。
感謝閱讀~~
相關文章
- Android Activity的啟動過程Android
- ORACLE啟動過程淺析Oracle
- Android中Activity啟動過程探究Android
- Activity啟動過程分析
- 淺析Spring Framework框架容器啟動過程SpringFramework框架
- 根Activity元件的啟動過程元件
- Android系統原始碼分析--Activity啟動過程Android原始碼
- 一張圖弄清Activity的啟動過程
- App 啟動過程(含 Activity 啟動過程) | 安卓 offer 收割基APP安卓
- Android啟動過程剖析-深入淺出Android
- ORACLE啟動過程簡析Oracle
- Activity的啟動過程第二篇
- Android 啟動過程簡析(一)之 init 程式Android
- android Activity的啟動模式 作用簡析+demo詳解Android模式
- Flutter Android 端啟動流程淺析FlutterAndroid
- Android 之 Activity 生命週期的淺析(二)Android
- Android 之 Activity 生命週期淺析(一)Android
- Android Service的啟動過程Android
- ORACLE關閉過程淺析Oracle
- Android App啟動過程AndroidAPP
- 淺析Java程式的執行過程Java
- 框架層理解Activity生命週期(APP啟動過程)框架APP
- 淺談 iOS 應用啟動過程iOS
- Android-Activity的啟動模式Android模式
- C程式編譯過程淺析C程式編譯
- iOS效能優化過程淺析iOS優化
- Android啟動過程深入解析Android
- Android 系統啟動過程Android
- Android深入四大元件(六)Android8.0 根Activity啟動過程(前篇)Android元件
- Android深入四大元件(七)Android8.0 根Activity啟動過程(後篇)Android元件
- 【Android原始碼】Service的啟動過程Android原始碼
- 【Android原始碼】Activity的啟動流程Android原始碼
- Spring MVC實現過程淺析SpringMVC
- RecyclerView 之 Adapter 的簡化過程淺析ViewAPT
- Android系統啟動過程剖析Android
- Android的activity的四種啟動方式Android
- Android Activity啟動模式全面解析Android模式
- [Android]Android Activity 啟動模式詳解Android模式