接上篇: Activity的啓動流程(一):ActivityManagerService部分java
上一篇咱們分析了activity在AndroidManagerService部分的啓動流程,這一篇咱們再來看一下activity在應用進程部分的啓動流程。學習activity在應用進程部分的啓動流程對於咱們深刻理解android應用的工做原理,特別是學習一些插件化方面的知識是頗有幫助的,由於上一篇中介紹的啓動流程大部分位於AMS中,AMS是一個系統服務進程,咱們沒法對其進行修改,而本篇介紹的啓動流程則位於應用進程中,咱們能夠利用反射等技術手段對其進行修改,某些插件化技術的核心原理就是經過對這部分的代碼進行hook,以達到替換要啓動的activity的目的。android
在上一篇的結尾處咱們能夠看到,AMS最後調用了ActivityThread的scheduleLaunchActivity方法,activity的啓動流程從AMS進程進入到了應用進程:緩存
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
複製代碼
咱們來看一下ActivityThread中的scheduleLaunchActivity方法:markdown
源碼路徑:\frameworks\base\core\java\android\app\ActivityThread.java
@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;
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方法中,將接收到的參數都封裝到了一個ActivityClientRecord對象中。從名字就能夠看出,ActivityClientRecord是activity在客戶端的一個記錄,主要封裝了activity的一些相關信息。app
在scheduleLaunchActivity方法的最後調用了sendMessage方法發送了一個消息,咱們來看一下sendMessage方法:async
private void sendMessage(int what, Object obj) {
sendMessage(what, obj, 0, 0, false);
}
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);
}
複製代碼
能夠看到sendMessage方法就是構建了一個Message對象,並經過mH這個對象進行了發送。很明顯mH是一個Handler對象,這裏是使用的Android的消息機制來進行消息分發。mH是一個類名爲H的實例,而H則繼承自Handler。mH主要用來處理主線程中的一些事件。使用消息機制來進行activity的啓動能夠保證Activity的啓動是在主線程中進行的。該消息最終會被mH的handleMessage方法進行處理,源碼以下:ide
private class H extends Handler {
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;
...
}
...
}
}
複製代碼
在handleMessage方法中,首先調用了getPackageInfoNoCheck,並將返回值賦值給了r的packageInfo變量。getPackageInfoNoCheck返回的是一個LoadedApk對象,該對象主要封裝了一些APK相關的信息。以後系統又調用了handleLaunchActivity方法來進一步進行activity的啓動。oop
先來看一下getPackageInfoNoCheck方法的代碼:post
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, boolean securityViolation, boolean includeCode, boolean registerPackage) {
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {
ref = null;
} else if (includeCode) {
// 註釋1:查看是否有緩存
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
...
//註釋2:若是沒有緩存,則建立新LoadedApk對象
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
...
if (differentUser) {
// Caching not supported across users
} else if (includeCode) {
// 註釋3:將LoadedApk對象放入緩存
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
複製代碼
首先,在註釋1處,先嚐試從mPackages對象中獲取這個LoadedApk對象,若是獲取不到的話,則會在註釋2處建立一個新的LoadedApk對象,並在註釋3處將這個LoadedApk加入到mPackages中。學習
咱們再來看一下handleLaunchActivity方法的代碼:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
// 註釋1:初始化WindowManager,經過Binder獲取WindowServiceManager的本地代理
WindowManagerGlobal.initialize();
// 註釋2:建立Activity
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
Bundle oldState = r.state;
// 註釋3
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}
...
}
複製代碼
在註釋1處,經過調用 WindowManagerGlobal.initialize()來對WindowManager進行了初始化,WindowManger是WindowManagerService在客戶端的一個代理對象,而WindowManagerService與ActivityManagerService相似,也是一個系統服務,主要用來對窗口的顯示進行控制。客戶端經過WindowManger對象,利用Binder機制來與WindowManagerService進行通訊。
在註釋2處經過performLaunchActivity來建立了Activity的實例,至此咱們要啓動的Activity實例終於被建立出來了。
在註釋3處則調用了handleResumeActivity方法使activity進入resume狀態。
下面咱們來看一下performLaunchActivity和handleResumeActivity具體對activity作了哪些初始化工做。
performLaunchActivity方法的源碼以下:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
ComponentName component = r.intent.getComponent();
...
// 註釋1:爲activity建立context
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
// 註釋2:建立activity實例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} ...
try {
...
if (activity != null) {
...
appContext.setOuterContext(activity);
// 註釋3
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);
...
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
// 設置主題
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
// 註釋4:調用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) {
//註釋5:進入start狀態
activity.performStart();
r.stopped = false;
}
...
}
r.paused = true;
mActivities.put(r.token, r);
} ...
return activity;
}
複製代碼
在註釋1處,系統首先爲activity建立了context對象,並經過這個context對象獲取了一個ClassLoader,用於加載要啓動的activity。
在註釋2處,經過調用mInstrumentation的newActivity方法建立了activity的實例。
在註釋3處調用了activity的attach方法來對activity進行一些初始化工做。
在註釋4處調用了mInstrumentation的callActivityOnCreate方法,從這個方法的名字就能夠看出,該方法內部調用了activity的onCreate方法。
在註釋5處調用了activity的performStart()方法,使activity進入start狀態。
咱們首先來看mInstrumentation的newActivity方法:
源碼路徑:\frameworks\base\core\java\android\app\Instrumentation.java public Activity newActivity(ClassLoader cl, String className, Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
複製代碼
newActivity方法只有一行代碼,就是經過反射加載了要啓動的activity類並建立了一個實例對象。
咱們再來看一下activity的attach方法作了哪些初始化工做:
源碼路徑:\frameworks\base\core\java\android\app\Activity.java final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
// 註釋1:爲activity建立window對象
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
//設置軟鍵盤狀態模式
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
// 註釋2:初始化一些成員變量
mUiThread = Thread.currentThread();
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
// 註釋3:爲window設置windowManager
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
mWindow.setColorMode(info.colorMode);
}
複製代碼
在註釋1處爲該activity建立了一個window對象,能夠看到這個window對象實際上是一個PhoneWindow對象。在Android系統中,每一個Activity都對應一個window對象,window主要和activity的窗口顯示有關。
在註釋2處爲該activity初始化了一些成員變量,如主線程、ui線程、application對象等。
在註釋3處爲window設置了WindowManager對象。
看完了activity的attach方法,咱們再來看Instrumentation的callActivityOnCreate方法:
源碼路徑:\frameworks\base\core\java\android\app\Instrumentation.java public void callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState) {
prePerformCreate(activity);
activity.performCreate(icicle, persistentState);
postPerformCreate(activity);
}
複製代碼
能夠看到在callActivityOnCreate方法中又調用了activity.performCreate來進一步初始化activity。performCreate方法的源碼以下:
源碼路徑:\frameworks\base\core\java\android\app\Activity.java final void performCreate(Bundle icicle, PersistableBundle persistentState) {
restoreHasCurrentPermissionRequest(icicle);
// 註釋1:調用onCreate
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
// 註釋2
performCreateCommon();
}
複製代碼
在註釋1處直接調用了onCreate方法,咱們一般會重寫activity的onCreate方法來進行一些自定義的初始化工做。在註釋2處又調用了performCreateCommon方法,咱們來看一下該方法的源碼:
final void performCreateCommon() {
mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, false);
mFragments.dispatchActivityCreated();
mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
}
複製代碼
能夠看到在performCreateCommon方法中調用了mFragments的dispatchActivityCreated方法,該方法內部會通知activity內的相關fragment,並觸發這些fragment的onActivityCreated方法。
回到ActivityThread的handleLaunchActivity方法中。在分析完performLaunchActivity方法後,咱們再來看一下handleResumeActivity方法作了哪些工做。handleResumeActivity方法代碼以下:
源碼路徑:\frameworks\base\core\java\android\app\ActivityThread.java final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
ActivityClientRecord r = mActivities.get(token);
...
// 註釋1
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
final Activity a = r.activity;
...
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
...
} else if (!willBeVisible) ...
cleanUpPendingRemoveWindows(r, false /* force */);
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
...
WindowManager.LayoutParams l = r.window.getAttributes();
...
}
...
// 通activity manager該activity已經處於resumed狀態
if (reallyResume) {
try {
ActivityManager.getService().activityResumed(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
} else {
...
}
}
複製代碼
handleResumeActivity方法的代碼很長,可是咱們不用糾結於代碼細節。在註釋1處調用了performResumeActivity,後面的代碼都是一些與window、decorView、windowManager相關的操做,不難猜出是與activity的顯示有關,咱們在這裏就不深刻分析了。咱們主要來看一下performResumeActivity方法:
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (localLOGV) Slog.v(TAG, "Performing resume of " + r
+ " finished=" + r.activity.mFinished);
if (r != null && !r.activity.mFinished) {
...
try {
...
r.activity.performResume();
...
} ...
}
return r;
}
複製代碼
performResumeActivity方法主要是調用了activity的performResume方法:
final void performResume() {
...
//調用activity的onResume方法
mInstrumentation.callActivityOnResume(this);
...
//通知fragment進入Resume狀態
mFragments.dispatchResume();
mFragments.execPendingActions();
...
}
複製代碼
首先,系統調用了mInstrumentation的callActivityOnResume,在callActivityOnResume方法內部會直接調用activity的onResume方法,這點與以前調用onCreate方法比較類似,這裏就再也不進一步分析了。這樣,activity就進入生命週期的Resume階段了。
咱們對這部分的activity啓動流程進行一下總結:
至此activity的建立流程就分析完了,本人水平有限,若是有哪裏寫的很差還望各位大佬多多指點。關於啓動流程中應用進程的建立部分並無在這裏進行介紹,由於這部份內容比較多,以後會單獨寫一篇文章介紹應用進程的建立流程。