關(guān)于Activity需要知道的更多內(nèi)容
前言
Activity作為作為四大組件中我們最常見的一個(gè)組件,經(jīng)常接觸使用,但是往往每次讓我們對(duì)這個(gè)組件進(jìn)行說明的時(shí)候,我們只知道它的幾個(gè)生命周期,幾種啟動(dòng)模式,但是具體的更多的就講不出來了。
ps:我在寫這個(gè)之前實(shí)際上也是一知半解,所以今天我們一起去看看Activity更多的東西,源碼版本為 android-26
- 1、Application的創(chuàng)建
- 2、Activity的創(chuàng)建和生命周期
一、Application的創(chuàng)建
我們知道,java程序想運(yùn)行都是通過調(diào)用main方法來啟動(dòng),我們的Android應(yīng)用程序也是如此,但是我們每次都是直接點(diǎn)擊手機(jī)屏幕的應(yīng)用圖標(biāo)就直接啟動(dòng)了app,這時(shí)候難免有疑惑,我們?yōu)槭裁床恍枰{(diào)用main方法就可以直接啟動(dòng)我們的程序呢,雖然我們沒有直接的去寫main方法,但是實(shí)際上還是通過ActivityThread類的main方法來作為我們應(yīng)用程序的入口。
# ActivityThread類
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();//1、這邊new了一個(gè)ActivityThread對(duì)象
thread.attach(false);//2、這邊去進(jìn)行連接,連接什么?
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在ActivityThread類中,能看到一個(gè)main方法,它就是我們程序的入口,在注釋1的地方,會(huì)去創(chuàng)建一個(gè)ActivityThread對(duì)象,在注釋2的地方,調(diào)用thread的attach方法去連接,具體的連接什么我們繼續(xù)看下面的代碼
#ActivityThread類
private void attach(boolean system) {
...
if (!system) {
...
final IActivityManager mgr = ActivityManager.getService();//1、通過AIDL,獲取AMS的代理對(duì)象IActivityManager
try {
mgr.attachApplication(mAppThread);//2、這邊將AMS和我們的應(yīng)用進(jìn)程application進(jìn)行連接
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
...
}
}
關(guān)于AIDL,這邊不進(jìn)行展開,我們關(guān)心的是注釋2,這邊通過AIDL將AMS和我們應(yīng)用進(jìn)程application進(jìn)行連接,具體的是調(diào)用ActivityManagerService的attachApplication方法進(jìn)行連接。
#ActivityManagerService類
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();//1、獲取pid
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);//2、傳入pid進(jìn)行連接
Binder.restoreCallingIdentity(origId);
}
}
這邊的注釋1通過Binder對(duì)象獲取應(yīng)用的pid,注釋2處調(diào)用attachApplicationLocked的方法傳入pid連接application。需要注意的這邊加了synchronized關(guān)鍵字,表示我們需要等待這里執(zhí)行完畢才能下一步,也就是說我們一個(gè)應(yīng)用需要當(dāng)我們application被連接后才能走下面的流程。
##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
ProcessRecord app; //1、進(jìn)程記錄類,保存相關(guān)的信息
long startTime = SystemClock.uptimeMillis();
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid); //2、根據(jù)id獲取相關(guān)信息賦值給記錄對(duì)象
}
}
...
if (app.instr != null) { //3、判斷進(jìn)程是否正在活躍
//Application 4、綁定到當(dāng)前線程
thread.bindApplication(processName, appInfo, providers, app.instr.mClass,
profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection,
testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()),
app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, isAutofillCompatEnabled);
} else {
//Application 4、綁定到當(dāng)前線程
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode, mBinderTransactionTrackingEnabled,
enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled);
}
...
// See if the top visible activity is waiting to run in this process...
//查看頂部可見活動(dòng)是否正在等待在此進(jìn)程中進(jìn)行
if (normalMode) {
try {
//TODO 5、Activity創(chuàng)建的分析
//檢測top的Activity是否在運(yùn)行中等待
if (mStackSupervisor.attachApattachApplicationplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
//查看在此進(jìn)程中進(jìn)行的服務(wù)
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
// Check if a next-broadcast receiver is in this process...
//查看在此進(jìn)程中進(jìn)行的廣播接收者
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);
badApp = true;
}
}
// Check whether the next backup agent is in this process...
//檢測下一個(gè)備份代理是否在此進(jìn)程中
if (!badApp && mBackupTarget != null && mBackupTarget.app == app) {
if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,
"New app is backup target, launching agent for " + app);
notifyPackageUse(mBackupTarget.appInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_BACKUP);
try {
thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
mBackupTarget.backupMode);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);
badApp = true;
}
}
...
}
看具體的attachApplicationLocked方法里面,注釋1處創(chuàng)建了一個(gè)進(jìn)程記錄對(duì)象用來保存進(jìn)程的相關(guān)信息,注釋2根據(jù)id獲取到相關(guān)信息賦值給記錄對(duì)象,注釋3先判斷進(jìn)行是否活躍,然后調(diào)用bindApplication的方法進(jìn)行application的綁定,這邊的thread是IApplicationThread對(duì)象,IApplicationThread它是一個(gè)AIDL的接口,是系統(tǒng)進(jìn)程調(diào)用應(yīng)用進(jìn)程的接口,它的實(shí)現(xiàn)類是ApplicationThread,是一個(gè)在ActivityThread的內(nèi)部類,注釋5的地方是關(guān)于Activity的創(chuàng)建,我們這邊先跳過,等我們將Application進(jìn)行綁定完成后在來分析。
##ActivityThread.ApplicationThread
public final void bindApplication(String processName, ApplicationInfo appInfo...,String buildSerial) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);//1、添加核心設(shè)置
//2、將bindApplication帶進(jìn)來的信息封裝到AppBindData類中,通過handler發(fā)送出去
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
...
sendMessage(H.BIND_APPLICATION, data);//3、將data通過handler發(fā)送出去,具體的WHAT 是 H.BIND_APPLICATION
}
在注釋1會(huì)去添加一些核心的設(shè)置,我們這邊就不去關(guān)注,我們看注釋2的地方,去將帶進(jìn)來的信息封裝到data中然后在注釋3通過handler發(fā)送出去,具體的WHAT 是 H.BIND_APPLICATION。H是一個(gè)繼承Handler的子類,這邊我們?nèi)タ聪孪⑹侨绾伪环职l(fā)處理的。
##ActivityThread.H
public void handleMessage(Message msg) {
...
switch (msg.what) {
...
case BIND_APPLICATION:
//1、這邊進(jìn)行handler消息的處理 處理創(chuàng)建Application的消息
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData) msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
...
}
這邊注釋1處理創(chuàng)建Application的消息,調(diào)用handleBindApplication的方法去綁定application
##ActivityThread
private void handleBindApplication(AppBindData data) {
final InstrumentationInfo ii;//1、創(chuàng)建InstrumentationInfo對(duì)象
...
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); 2、 //獲取application的context上下文
// 3、加載instrumentation
if (ii != null) {
...
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection); //4、instrumentation初始化
...
} else {
mInstrumentation = new Instrumentation();
}
try {
Application app = data.info.makeApplication(data.restrictedBackupMode, null);//5、通過makeApplication方法創(chuàng)建application
...
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
} catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);//6、回調(diào)application的onCreate方法
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
這個(gè)方法里面處理了許多事情,注釋1創(chuàng)建了一個(gè)InstrumentationInfo對(duì)象,在注釋2獲取了application的上下文,注釋3和4去加載并初始化了InstrumentationInfo,注釋5是我們的關(guān)鍵地方,通過調(diào)用makeApplication的方法創(chuàng)建了我們的application,我們看下makeApplication的方法都做了什么操作。然后在注釋6調(diào)用InstrumentationInfo去回調(diào)application的onCreate方法,到這里我們的application就創(chuàng)建并且回到了我們熟悉onCreate方法。
##LoadedApk
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {//1、如果mApplication不為null,直接返回mApplication對(duì)象
return mApplication;
}
Application app = null;
//如果是有自定義的application,就用這個(gè),如果沒有,就用系統(tǒng)的application
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
//2、獲得類加載器然后通過反射去new一個(gè)Appliction
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
...
}
mActivityThread.mAllApplications.add(app);
mApplication = app;//3、賦值給mApplication
if (instrumentation != null) {//4、這邊會(huì)為instrumentation是為null的
try {
instrumentation.callApplicationOnCreate(app);//5、這邊如果instrumentation不為null,才能執(zhí)行到這里
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
...
}
}
}
...
return app;
}
這邊我們首先判斷mApplication如果不為null,直接返回這個(gè)對(duì)象,如果為null的話,我們通過類加載然后反射去new出一個(gè)application對(duì)象并且賦值給mApplication,還有這邊因?yàn)槲覀冊(cè)谡{(diào)用makeApplication方法時(shí)傳入的Instrumentation是個(gè)null對(duì)象,所以我們這邊不會(huì)去執(zhí)行
callApplicationOnCreate回調(diào)onCreate方法的。具體的回調(diào)onCreate會(huì)在上面的源碼注釋6的地方去執(zhí)行回調(diào)。
二、Activity的創(chuàng)建
這邊我們首先需要知道Activity的狀態(tài)和生命周期
狀態(tài):運(yùn)行、暫停、停止、銷毀(運(yùn)行和暫停是不可見的,停止和銷毀是不可見的)
生命周期:包括了常見的onCreate、onResume、onStart、onPause、onStop、onDestory等
上面的分析過程中我們?cè)贏ctivityManagerService類中留了一個(gè)
##ActivityManagerService
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
//5、檢測最可見的Activity是否在運(yùn)行進(jìn)程中等待,如果再則創(chuàng)建Activity
//TODO 待分析Activity的創(chuàng)建
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
}
...
這邊我們對(duì)它進(jìn)行深入下看看是如何創(chuàng)建的
##ActivityStackSupervisor
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
...
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = stacks.get(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
//ActivityRecord來維護(hù)Activity運(yùn)行時(shí)的狀態(tài)信息,需要將Activity綁定到AMS,ActivityRecord才能開始Activity的生命周期
ActivityRecord hr = stack.topRunningActivityLocked();
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (realStartActivityLocked(hr, app, true, true)) {//1、真正的創(chuàng)建Activity
didSomething = true;
}
} catch (RemoteException e) {
throw e;
}
}
}
}
}
...
return didSomething;
}
在realStartActivityLocked我們會(huì)創(chuàng)建Activity
##ActivityStackSupervisor
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
r.startFreezingScreenLocked(app, 0);//1、開始屏幕相關(guān)的啟動(dòng)
// schedule launch ticks to collect information about slow apps.
r.startLaunchTickingLocked();//2、啟動(dòng)定時(shí)鎖定
r.app = app;
app.waitingToKill = null;
r.launchCount++;//3、每啟動(dòng)一次launchCount的數(shù)量自增
r.lastLaunchTime = SystemClock.uptimeMillis();//4、修改最后一次的啟動(dòng)時(shí)間
final ActivityStack stack = task.getStack();
try {
...
//5、根據(jù)具體的包名,通知應(yīng)用
mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
...
//6、調(diào)用ApplicationThread的scheduleLaunchActivity 方法去啟動(dòng)LaunchActivity
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global and
// override configs.
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
...
} catch (RemoteException e) {
...
}
...
if (isFocusedStack(stack)) {
mService.startSetupActivityLocked();7、開始設(shè)置活動(dòng)鎖
}
if (r.app != null) {
mService.mServices.updateServiceConnectionActivitiesLocked(r.app);//8、更新服務(wù)連接活動(dòng)鎖
}
return true;
}
這邊的注釋很多,但是我們主要關(guān)心的是注釋6,這邊調(diào)用ApplicationThread的scheduleLaunchActivity 方法去啟動(dòng)LaunchActivity,我們回到ApplicationThread
##ActivityThread.ApplicationThread
@Override
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
..., ProfilerInfo profilerInfo) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
...
sendMessage(H.LAUNCH_ACTIVITY, r);//通過handler發(fā)送啟動(dòng)Activity的消息
}
這邊是不是很眼熟,我們剛剛的application的綁定也是通過handler去發(fā)送消息去處理(這邊我們能發(fā)現(xiàn)handler是有多么重要了吧,哈哈),我們?nèi)ctivityThread的子類H去看下具體的activity創(chuàng)建的消息處理
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {//1、接收到關(guān)于創(chuàng)建Activity的消息,進(jìn)行處理
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");//2、去創(chuàng)建LaunchActivity
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
根據(jù)message的what值我們找到了具體的消息處理,這邊會(huì)通過handleLaunchActivity去處理我們Activity創(chuàng)建
##ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);//1、去執(zhí)行LaunchActivity
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);//2、處理可見Activity
...
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
//3、這邊如何activity是個(gè)null的對(duì)象,直接通過ActivityManagerService調(diào)用finishActivity去關(guān)閉掉
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
這邊我們先看注釋1的performLaunchActivity方法
##ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
ActivityInfo aInfo = r.activityInfo;//1、獲取Activity的信息
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
...
ContextImpl appContext = createBaseContextForActivity(r);//2、獲取Acitivty的上下文
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();//3、獲取類加載器,使用cl(類加載器)加載出Activity,再使用反射new出Activity
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);
}
} catch (Exception e) {
...
}
try {
//4、這邊又去調(diào)用一次makeApplication方法
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
...
appContext.setOuterContext(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()) {//5、這邊去調(diào)用Activity的onCreate方法
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
}
return activity;
}
在注釋3我們會(huì)發(fā)現(xiàn)這邊是獲取類加載去然后通過反射去new出一個(gè)Activity,然后在注釋5去回調(diào)Activity的onCreate方法,到這邊我們就能去調(diào)用我們的setContentView去加載布局了。注釋4的地方又調(diào)用了一次makeApplication方法,如果Application不為null,直接返回application對(duì)象。
現(xiàn)在我們回到上一個(gè)源碼的注釋2那里,看看handleResumeActivity都做了什么?
##ActivityThread
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
...
r = performResumeActivity(token, clearHide, reason);
...
}
這個(gè)方法里面有很多代碼,我們只需要去看performResumeActivity方法
##ActivityThread
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide, String reason) {
...
r.activity.performResume();//主要是這個(gè)方法
...
return r;
}
這邊是調(diào)用Activity的performResume方法
##Activity
final void performResume() {
performRestart();
mFragments.execPendingActions();
mLastNonConfigurationInstances = null;
mCalled = false;
// mResumed is set by the instrumentation
mInstrumentation.callActivityOnResume(this);//回調(diào)Activity的onResume方法
}
到這邊我們就能發(fā)現(xiàn)它跟Activity的onCreate的回調(diào)是類似的,都是通過mInstrumentation.callActivityxxx去回調(diào)執(zhí)行。