Activity啟動流程分析記錄(Api26)
直觀流程圖
具體流程分析
- Activity呼叫startActivity,雖然startActivity有很多過載函式,但是最終也會呼叫Activity中的startActivityForResult方法,在startActivityForResult中有一個mParent的null判斷,mParent代表的是ActivityGroup,ActivityGroup用於在一個Activity中放入多個子Activity,已經被廢棄,使用Fragmemt和FragmentManager替代,所以主要看mParent==null
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//呼叫Instrumentation的execStartActivity方法
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
//返回結果不為空,證明返回的intent中含有引數,將引數作為結果返回
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {
....忽略
}
}
- 在Instrumentation.execStartActivity方法程式碼,具體關注ActivityManager.getService().startActivity方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result , intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
上面這段程式碼中,可以發現啟動Activity真正的實現由ActivityManager.getService()的startActivity方法完成,ActivityManager.getService()方法其實是一個IActivityManager型別的Binder物件,這個Binder物件使用一個單例模式進行封裝,保證全域性只有一個IActivityManager物件.
在執行完 ActivityManager.getService().startActivity方法後,還有一句checkStartActivityResult(result , intent);這句程式碼就是用於檢查啟動的Activity的結果,當無法正常啟動Activity的時候,就會丟擲異常,其中最常見的一個異常資訊就是
Unable to find explicit activity class ** have you declared this activity in your AndroidManifest.xml?
- 通過上面的流程分析,現在發現具體的Activity啟動主要就是在AMS中的startActivity方法.AMS中的startActivity又呼叫了startActivityAsUser方法,這裡又將Activity的啟動轉移到了ActivityStarter的startActivityMayWait方法中,
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
...
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null,
"startActivityAsUser");
}
- 饒了一大圈其實就是在ActivityStarter內部,ActivityStack,ActivityStackSupervisor之間不斷呼叫,最終落在ActivityStackSupervisor的realStartActivityLocked方法中,其中注意方法中以下程式碼
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, // override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
scheduleLaunchActivity這個方法是在realStartActivityLocked中被呼叫的,app.thread物件是IApplicationThread,這個IApplicationThread是一個IBinder物件,這個介面的實現類在ActivityThread中,一個私有的內部類,ApplicationThread ,該類繼承自IApplicationThread.Stub,實現了IApplicationThread所有的抽象方法.
scheduleLaunchActivity就是啟動Activity的方法,通過傳送一個啟動activity的訊息交給handler處理,handler接收到訊息後呼叫handleLaunchActivity方法,然後呼叫了handleResumeActivity方法呼叫被啟動的Activity的onResume生命週期方法.
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) {
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
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;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
}
handleLaunchActivity中呼叫了performLaunchActivity和handleResumeActivity方法
- 在performLaunchActivity中,通過呼叫了Instrumentation的newActivity方法,通過反射建立了Activity物件,呼叫LoadedApk中的makeApplication建立了Application物件,其內部實現也是通過反射.
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
忽略部分初始化程式碼...
//建立Context的實現類
ContextImpl appContext = createBaseContextForActivity(r);
//建立Activity物件
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
...
//建立Application物件
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
//Activity與Context建立聯絡,同時完成Activity與Window的關聯.
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);
}
Activity的啟動流程大體如此,大部分邏輯都是參考<<Android開發藝術探索>>,但是由於書中的原始碼版本是Android5.0,而我在學習的時候使用的原始碼是Android8.0,所以可能會有部分程式碼有出入,但是整體結構和邏輯都是一樣的,並不影響對Activity啟動的掌握
相關文章
- Activity啟動流程分析
- activity 啟動流程分析
- Activity啟動流程原始碼分析原始碼
- Android Activity啟動流程原始碼分析Android原始碼
- Android原始碼分析:Activity啟動流程Android原始碼
- 庖丁解牛 Activity 啟動流程
- 從Activity的啟動流程理解Binder
- Activity啟動過程分析
- app啟動流程,activity啟動流程時序圖,binder相關資料APP時序圖
- 【Android原始碼】Activity的啟動流程Android原始碼
- Activity的起步流程分析
- Activity 的 "啟動流程"(基於 Android 9.0)Android
- 基於8.0原始碼解析:Activity啟動流程原始碼
- 圖解Activity啟動流程,進階高階圖解
- Activity 啟動流程學習總結(附原始碼流程圖)原始碼流程圖
- Activity啟動分析(一)--ActivityThreadthread
- Unbound啟動流程分析
- 深入理解Activity啟動流程和AMS框架(一)框架
- 深入理解Activity啟動流程和AMS框架(二)框架
- 深入理解Activity啟動流程和AMS框架(三)框架
- App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析APPAndroid
- Activity啟動分析(二)--建立Window和ViewView
- 原始碼閱讀之Activity啟動與App啟動流程 - Android 9.0原始碼APPAndroid
- 原始碼閱讀之Activity啟動與App啟動流程 – Android 9.0原始碼APPAndroid
- FlutterApp啟動流程分析FlutterAPP
- nodejs啟動流程分析NodeJS
- Android 8.0 原始碼分析 (四) Activity 啟動Android原始碼
- Activity啟動模式模式
- Flutter啟動流程原始碼分析Flutter原始碼
- Linux:uboot啟動流程分析Linuxboot
- apiserver原始碼分析——啟動流程APIServer原始碼
- 深入理解Android 之 Activity啟動流程(Android 10)Android
- Activity生命週期與啟動模式筆記模式筆記
- activity的啟動模式模式
- 【系統之音】Activity啟動流程——史上最全最簡潔易懂版
- Android之Activity啟動流程詳解(基於api28)AndroidAPI
- Android應用啟動流程分析Android
- Flutter系列三:Flutter啟動流程分析Flutter