關(guān)于activity啟動(dòng)流程的分析蚌铜,實(shí)際上非常的繁瑣,牽扯到與ams的交互非常之多湿酸,很多源碼的執(zhí)行在system_server進(jìn)程中伍派,所以并不打算在system_server端做過(guò)多很細(xì)節(jié)的分析,本文主要分析以下幾點(diǎn):
1.都知道每個(gè)activiy在onAttach有個(gè)token來(lái)讓ams標(biāo)示此activity屈张,那token變量從哪來(lái)擒权?
2.當(dāng)activity a打開(kāi)activity b時(shí),a的onPause和a的onStop執(zhí)行的時(shí)機(jī)阁谆?
3.當(dāng)activity為singleInstance或者singleTop模式時(shí)碳抄,再次打開(kāi)會(huì)走onNewIntent,那是在哪里調(diào)用的呢?
4.每個(gè)activity以及view的onSaveInstanceState()和onRestoreInstanceState()調(diào)用時(shí)機(jī)场绿。
5.activity中設(shè)置啟動(dòng)模式后剖效,在ams具體的實(shí)現(xiàn)原理
6.從launcher啟動(dòng)activity和一般啟動(dòng)的區(qū)別
7.用Context開(kāi)啟activity要設(shè)置new_task的標(biāo)志位的根本原因
關(guān)于binder的跨進(jìn)程通訊的知識(shí)點(diǎn):
請(qǐng)看老羅的分析,個(gè)人感覺(jué)還是很到位的
https://blog.csdn.net/luoshengyang/article/details/6642463
當(dāng)調(diào)用startActivity時(shí)裳凸,會(huì)間接調(diào)用startActivityForResult方法
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
Instrumentation.ActivityResult ar =
//重點(diǎn)一:
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);
}
}
}
這里調(diào)用了mInstrumentation的execStartActivity方法,可以看到參數(shù)如下
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
這里有兩個(gè)binder對(duì)象,第一個(gè)binder對(duì)象時(shí)一個(gè)applicationThread對(duì)象劝贸,這其實(shí)和thread沒(méi)有任何關(guān)系姨谷,這個(gè)binder是ams要傳給主進(jìn)程的回掉對(duì)象,可以看到
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
private int mLastProcessState = -1;
private void updatePendingConfiguration(Configuration config) {
synchronized (mResourcesManager) {
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(config)) {
mPendingConfiguration = config;
}
}
}
....
這里簡(jiǎn)單說(shuō)下IApplicationThread.Stub類映九,就是進(jìn)程a和進(jìn)程b通訊時(shí)梦湘,進(jìn)程b給進(jìn)程a的回調(diào)方法:
1.首先進(jìn)程a會(huì)得到進(jìn)程b的代理對(duì)象,然后調(diào)用進(jìn)程b的方法件甥,此時(shí)經(jīng)過(guò)了一次跨進(jìn)程通訊捌议,a為客戶端,b為服務(wù)端
2.當(dāng)然進(jìn)程a也可以通過(guò)writeStrongBinder給進(jìn)程b傳遞一個(gè)binder對(duì)象
3.當(dāng)在進(jìn)程b時(shí)引有,會(huì)調(diào)用其asInterface方法瓣颅,當(dāng)然由于時(shí)跨進(jìn)程的,自然獲得的也是一個(gè)proxy對(duì)象譬正。
4.在進(jìn)程b合適的時(shí)機(jī)會(huì)調(diào)用Stub類里面的方法c(),此時(shí)由于b拿到的是一個(gè)proxy對(duì)象宫补,所以又進(jìn)行了一次跨進(jìn)程通訊檬姥,此時(shí)b變成了客戶端,a成了服務(wù)端
在了解完了此之后粉怕,我們知道execStartActivity方法會(huì)間接調(diào)用ams的startActivity方法從而進(jìn)程跨進(jìn)程通訊
/**
* @hide
*/
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
這段代碼的含義就不多說(shuō)了健民,不明白的可以看下老羅的https://blog.csdn.net/luoshengyang/article/details/6642463(主要功力不夠,講的不夠有深度)而ams的startActivity方法會(huì)間接調(diào)用ActivityStarter類的startActivityMayWait方法
//ActivityStarter
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
....
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
...
return res;
在startActivityLocked方法里會(huì)間接調(diào)用startActivity方法贫贝,而在ActivityStarter的startActivity方法里會(huì)創(chuàng)建activityRecord對(duì)象
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
options, sourceRecord);
....
ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid,
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode,
boolean _componentSpecified, boolean _rootVoiceInteraction,
ActivityStackSupervisor supervisor,
ActivityContainer container, ActivityOptions options, ActivityRecord sourceRecord) {
service = _service;
appToken = new Token(this);
info = aInfo;
launchedFromPid = _launchedFromPid;
launchedFromUid = _launchedFromUid;
可以看到在這里面新建了Token秉犹,可以說(shuō)token就是和每個(gè)activity綁定的,也就是一個(gè)activity的標(biāo)識(shí)符稚晚。
而activityRecord同樣也包含了以下信息
ProcessRecord app //跑在哪個(gè)進(jìn)程
TaskRecord task //跑在哪個(gè)task
ActivityInfo info // Activity信息
int mActivityType //Activity類型
ActivityState state //Activity狀態(tài)
ApplicationInfo appInfo //跑在哪個(gè)app
ComponentName realActivity //組件名
String packageName //包名
String processName //進(jìn)程名
int launchMode //啟動(dòng)模式
int userId // 該Activity運(yùn)行在哪個(gè)用戶id
在之后會(huì)調(diào)用ActivityStarter類的startActivityUnchecked方法
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
int result = START_CANCELED;
try {
mService.mWindowManager.deferSurfaceLayout();
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
} finally {
// If we are not able to proceed, disassociate the activity from the task. Leaving an
// activity in an incomplete state can lead to issues, such as performing operations
// without a window container.
if (!ActivityManager.isStartResultSuccessful(result)
&& mStartActivity.getTask() != null) {
mStartActivity.getTask().removeActivity(mStartActivity);
}
mService.mWindowManager.continueSurfaceLayout();
}
postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId, mSourceRecord,
mTargetStack);
return result;
}
這里又分為了四種情況:
第一種情況 打開(kāi)的activity是原本就在任務(wù)棧里崇堵,并且此activity是singleTask或者是singleInstance模式,那么就把這個(gè)activity放到第一個(gè)蜈彼,然后調(diào)用onNewIntent方法筑辨,最后調(diào)用resumeTargetStackIfNeeded 方法return ,具體看代碼
//ActivityStarter
....
setInitialState(r, options, inTask, doResume, startFlags,
sourceRecord, voiceSession,
voiceInteractor);
computeLaunchingTaskFlags();
computeSourceStack();
mIntent.setFlags(mLaunchFlags);
ActivityRecord reusedActivity = getReusableIntentActivity();
final int preferredLaunchStackId =
(mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;
final int preferredLaunchDisplayId =
(mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
// the device would otherwise leave the locked task.
if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {
mSupervisor.showLockTaskToast();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (mStartActivity.getTask() == null) {
mStartActivity.setTask(reusedActivity.getTask());
}
if (reusedActivity.getTask().intent == null) {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTask().setIntent(mStartActivity);
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
// as the first operation, in case the activity will be resumed as a result of later
// operations.
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
final TaskRecord task = reusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
// being started. In most cases this means we are resetting the task to its initial
// state.
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
// The above code can remove {@code reusedActivity} from the task, leading to the
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
// task reference is needed in the call below to
// {@link setTargetStackAndMoveToFrontIfNeeded}.
if (reusedActivity.getTask() == null) {
reusedActivity.setTask(task);
}
if (top != null) {
if (top.frontOfTask) {
// Activity aliases may mean we use different intents for the top activity,
// so make sure the task now has the identity of the new intent.
top.getTask().setIntent(mStartActivity);
}
ActivityStack.logStartActivity(AM_NEW_INTENT, mStartActivity, top.getTask());
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
}
sendPowerHintForLaunchStartIfNeeded(false /* forceSend */);
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
final ActivityRecord outResult =
outActivity != null && outActivity.length > 0 ? outActivity[0] : null;
// When there is a reused activity and the current result is a trampoline activity,
// set the reused activity as the result.
if (outResult != null && (outResult.finishing || outResult.noDisplay)) {
outActivity[0] = reusedActivity;
}
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do anything
// if that is the case, so this is it! And for paranoia, make sure we have
// correctly resumed the top activity.
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
setTaskFromIntentActivity(reusedActivity);
if (!mAddingToTask && mReuseTask == null) {
// We didn't do anything... but it was needed (a.k.a., client don't use that
// intent!) And for paranoia, make sure we have correctly resumed the top activity.
resumeTargetStackIfNeeded();
if (outActivity != null && outActivity.length > 0) {
outActivity[0] = reusedActivity;
}
return START_TASK_TO_FRONT;
}
}
從上面代碼中可以看到有個(gè)reusedActivity變量是否為null的判斷幸逆,其實(shí)這取決于getReusableIntentActivity方法
private ActivityRecord getReusableIntentActivity() {
// We may want to try to place the new activity in to an existing task. We always
// do this if the target activity is singleTask or singleInstance; we will also do
// this if NEW_TASK has been requested, and there is not an additional qualifier telling
// us to still place it in a new task: multi task, always doc mode, or being asked to
// launch this as a new task behind the current one.
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| mLaunchSingleInstance || mLaunchSingleTask;
// If bring to front is requested, and no result is requested and we have not been given
// an explicit task to launch in to, and we can find a task that was started with this
// same component, then instead of launching bring that one to the front.
putIntoExistingTask &= mInTask == null && mStartActivity.resultTo == null;
ActivityRecord intentActivity = null;
if (mOptions != null && mOptions.getLaunchTaskId() != -1) {
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
if (mLaunchSingleInstance) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info, false);
} else if ((mLaunchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0) {
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
!mLaunchSingleTask);
} else {
// Otherwise find the best task to put the activity in.
intentActivity = mSupervisor.findTaskLocked(mStartActivity, mSourceDisplayId);
}
}
return intentActivity;
}
getReusableIntentActivity返回值是否為null還是取決于Intent中設(shè)置的flag和啟動(dòng)模式棍辕,當(dāng)設(shè)置了FLAG_ACTIVITY_NEW_TASK或者啟動(dòng)模式為singleTask,singleInstance之一的時(shí)候还绘,如果系統(tǒng)Task歷史中存在啟動(dòng)Activity實(shí)例楚昭,該函數(shù)一般返回值都不為null,相反其他的啟動(dòng)模式都是返回null的
在進(jìn)入了這個(gè)if語(yǔ)句以后我們可以看到
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
這段代碼是清除在此activity之上的任務(wù)棧的
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
這里是回調(diào)onNewIntent方法
reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);
.....
resumeTargetStackIfNeeded
這句代碼是把找到的activity設(shè)置到前臺(tái)拍顷,這也是處理singleInstance和singleTask的情況,resumeTargetStackIfNeeded代碼等會(huì)講
第二種情況 也就是說(shuō)是此activity在棧頂抚太,打開(kāi)的activity也是singleTop或者mLaunchSingleTask模式的話
在startActivityUnchecked方法中判斷dontStart的值
final boolean dontStart = top != null && mStartActivity.resultTo == null
&& top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
|| mLaunchSingleTop || mLaunchSingleTask);
if (dontStart) {
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked();
}
ActivityOptions.abort(mOptions);
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and the client said not to do
// anything if that is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
deliverNewIntent(top);
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, topStack.mStackId);
return START_DELIVERED_TO_TOP;
}
當(dāng)dontStart為true的話,表明此activity是在棧頂?shù)奈舭福藭r(shí)就不用在啟動(dòng)新的了尿贫,如果此activity的模式是mLaunchSingleTop或者mLaunchSingleTask或者設(shè)置了FLAG_ACTIVITY_SINGLE_TOP的flag的話,就直接調(diào)用resumeFocusedStackTopActivityLocked方法
第三種情況: 是new_task啟動(dòng)的activity踏揣,我們知道standard和singletop的模式下是沒(méi)有新開(kāi)棧的能力的庆亡,singleInstance獨(dú)自一個(gè)棧,
singleTask和taskAffinity有關(guān)捞稿,默認(rèn)是和根任務(wù)棧相同又谋,設(shè)置不同的話就會(huì)新開(kāi)棧,而new_task會(huì)新開(kāi)一個(gè)任務(wù)棧娱局,并且原來(lái)standard或者singletop屬性值也不會(huì)消失
// Should this be considered a new task?
int result = START_SUCCESS;
if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {
newTask = true;
result = setTaskFromReuseOrCreateNewTask(
taskToAffiliate, preferredLaunchStackId, topStack);
} else if (mSourceRecord != null) {
result = setTaskFromSourceRecord();
} else if (mInTask != null) {
result = setTaskFromInTask();
} else {
// This not being started from an existing activity, and not part of a new task...
// just put it in the top task, though these days this case should never happen.
setTaskToCurrentTopOrCreateNewTask();
}
if (result != START_SUCCESS) {
return result;
}
當(dāng)設(shè)置了FLAG_ACTIVITY_NEW_TASK標(biāo)記彰亥,并且要啟動(dòng)的Activity當(dāng)前沒(méi)有運(yùn)行在某個(gè)任務(wù)棧中的話,會(huì)調(diào)用setTaskFromReuseOrCreateNewTask方法來(lái)新建task
這種情況下衰齐,通常是我們說(shuō)的用Context.startActivity啟動(dòng)要加new_task標(biāo)志位的根本原因任斋,因?yàn)槿绻患拥脑挘捎趍SourceRecord也就是啟動(dòng)它的activity為null,并且mInTask為null(用 Context 啟動(dòng)耻涛,當(dāng)然不再棧內(nèi))自然會(huì)走到setTaskToCurrentTopOrCreateNewTask方法里仁卷,看名字和注釋就知道穴翩,把此task放進(jìn)了當(dāng)前的任務(wù)棧內(nèi),由于ContextImp對(duì)沒(méi)有new_task啟動(dòng)的activity做了攔截锦积,所以自然不會(huì)走到這里
第四種情況:正常的流程
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
// If the activity is not focusable, we can't resume it, but still would like to
// make sure it becomes visible as it starts (this will also trigger entry
// animation). An example of this are PIP activities.
// Also, we don't want to resume activities in a task that currently has an overlay
// as the starting activity just needs to be in the visible paused state until the
// over is removed.
mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// Go ahead and tell window manager to execute app transition for this activity
// since the app transition will not be triggered through the resume channel.
mWindowManager.executeAppTransition();
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
// will not update the focused stack. If starting the new activity now allows the
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
mTargetStack.addRecentActivityLocked(mStartActivity);
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredLaunchStackId,
preferredLaunchDisplayId, mTargetStack.mStackId);
return START_SUCCESS;
這里有2點(diǎn)說(shuō)下:
mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,
mOptions);
這里主要是調(diào)用ActivityStack的startActivityLocked方法芒帕,里面主要是windowManager對(duì)activity一些動(dòng)畫(huà)的處理
重點(diǎn)會(huì)走到
//ActivityStackSupervisor
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
if (r == null || r.state != RESUMED) {
mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
} else if (r.state == RESUMED) {
// Kick off any lingering app transitions form the MoveTaskToFront operation.
mFocusedStack.executeAppTransition(targetOptions);
}
return false;
}
可以看到如果 待啟動(dòng)Activity對(duì)應(yīng)的Task為前臺(tái)Task時(shí),調(diào)用該Task對(duì)應(yīng)ActivityStack的resumeTopActivityUncheckedLocked丰介,否則就調(diào)用前臺(tái)task的resumeTopActivityUncheckedLocked背蟆,一般來(lái)說(shuō)走的是第一個(gè)if
此方法會(huì)間接調(diào)用ActivityStack的resumeTopActivityInnerLocked方法
里面代碼太多了,依然是分小結(jié)來(lái)看
//activityStack
final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
這方法返回了一個(gè)next對(duì)象哮幢,簡(jiǎn)單來(lái)說(shuō)activiyRecord里包含了包名带膀,進(jìn)程信息,activity信息橙垢,上文已經(jīng)說(shuō)過(guò)垛叨,而判斷此activity的進(jìn)程是否存在調(diào)用調(diào)用next.app是否為null即可
//activityStack
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, next, false);
if (mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeTopActivityLocked: Pausing " + mResumedActivity);
pausing |= startPausingLocked(userLeaving, false, next, false);
}
mResumedActivity就是上一個(gè)activity,startPausingLocked方法就是讓上一個(gè)activity進(jìn)入pause狀態(tài)
if (pausing && !resumeWhilePausing) {
if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
"resumeTopActivityLocked: Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
// very soon and it would be a waste to let it get killed if it
// happens to be sitting towards the end.
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, true, null);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
如果要打開(kāi)的activity進(jìn)程存在柜某,就讓ams更新啟動(dòng)activity進(jìn)程的優(yōu)先級(jí)
這個(gè)lru和lrucache內(nèi)部實(shí)現(xiàn)無(wú)太大差別嗽元,無(wú)非就是把最近使用放到鏈表的頭或者鏈表尾,然后依次刪除不常用的
接下來(lái)看下調(diào)用onNewIntent和onResume的邏輯
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(
next.newIntents, next.appToken, false /* andPause */);
}
// Well the app will no longer be stopped.
// Clear app token stopped state in window manager if needed.
next.notifyAppResumed(next.stopped);
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
System.identityHashCode(next), next.getTask().taskId,
next.shortComponentName);
next.sleeping = false;
mService.showUnsupportedZoomDialogIfNeededLocked(next);
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(mService.mTopProcessState);
next.clearOptionsLocked();
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward(), resumeAnimOptions);
可以看到在newIntents不為null的情況下會(huì)調(diào)用scheduleNewIntent喂击,而這個(gè)newIntents就是在startActivityUnchecked中剂癌,在singleTop或者singleTask把intent放到list中的
而當(dāng)走到了scheduleResumeActivity時(shí),通過(guò)跨進(jìn)程調(diào)用了activityThread的handleResumeActivity方法
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;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
// Normally the ViewRoot sets up callbacks with the Activity
// in addView->ViewRootImpl#setView. If we are instead reusing
// the decor view we have to notify the view root that the
// callbacks may have changed.
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// If the window has already been added, but during resume
// we started another activity, then don't yet make the
// window visible.
} else if (!willBeVisible) {
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
在這里實(shí)現(xiàn)了windowManager添加decoreview的邏輯翰绊,有時(shí)間下一次來(lái)說(shuō)關(guān)于windowManager的細(xì)節(jié)
這里主要說(shuō)的是在執(zhí)行完onResume時(shí)會(huì)調(diào)用
Looper.myQueue().addIdleHandler(new Idler());
也就是handler空閑狀態(tài)下才調(diào)用的佩谷,此方法間接調(diào)用了
@Override
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
ActivityRecord r =
mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
if (stopProfiling) {
if ((mProfileProc == r.app) && (mProfileFd != null)) {
try {
mProfileFd.close();
} catch (IOException e) {
}
clearProfilerLocked();
}
}
}
}
Binder.restoreCallingIdentity(origId);
}
會(huì)調(diào)用activityIdleInternalLocked方法,繼續(xù)來(lái)看下
// Atomically retrieve all of the other things to do.
final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(r,
true /* remove */, processPausingActivities);
NS = stops != null ? stops.size() : 0;
if ((NF = mFinishingActivities.size()) > 0) {
finishes = new ArrayList<>(mFinishingActivities);
mFinishingActivities.clear();
}
if (mStartingUsers.size() > 0) {
startingUsers = new ArrayList<>(mStartingUsers);
mStartingUsers.clear();
}
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
} else {
stack.stopActivityLocked(r);
}
}
}
從processStoppingActivitiesLocked方法里找到要執(zhí)行onStop方法的activity监嗜,執(zhí)行stopActivityLocked方法谐檀,進(jìn)到里面就會(huì)調(diào)用scheduleStopActivity方法了,從未調(diào)用performStopActivityInner方法
private void performStopActivityInner(ActivityClientRecord r,
StopInfo info, boolean keepShown, boolean saveState, String reason) {
if (localLOGV) Slog.v(TAG, "Performing stop of " + r);
if (r != null) {
if (!keepShown && r.stopped) {
if (r.activity.mFinished) {
// If we are finishing, we won't call onResume() in certain
// cases. So here we likewise don't want to call onStop()
// if the activity isn't resumed.
return;
}
RuntimeException e = new RuntimeException(
"Performing stop of activity that is already stopped: "
+ r.intent.getComponent().toShortString());
Slog.e(TAG, e.getMessage(), e);
Slog.e(TAG, r.getStateString());
}
// One must first be paused before stopped...
performPauseActivityIfNeeded(r, reason);
if (info != null) {
try {
// First create a thumbnail for the activity...
// For now, don't create the thumbnail here; we are
// doing that by doing a screen snapshot.
info.description = r.activity.onCreateDescription();
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to save state of activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
}
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
if (r.state == null) {
callCallActivityOnSaveInstanceState(r);
}
}
if (!keepShown) {
try {
// Now we are idle.
r.activity.performStop(false /*preserveWindow*/);
} catch (Exception e) {
if (!mInstrumentation.onException(r.activity, e)) {
throw new RuntimeException(
"Unable to stop activity "
+ r.intent.getComponent().toShortString()
+ ": " + e.toString(), e);
}
}
r.stopped = true;
EventLog.writeEvent(LOG_AM_ON_STOP_CALLED, UserHandle.myUserId(),
r.activity.getComponentName().getClassName(), reason);
}
}
}
可以看到在調(diào)用performStop方法前裁奇,還調(diào)用了callCallActivityOnSaveInstanceState方法
private void callCallActivityOnSaveInstanceState(ActivityClientRecord r) {
r.state = new Bundle();
r.state.setAllowFds(false);
if (r.isPersistable()) {
r.persistentState = new PersistableBundle();
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state,
r.persistentState);
} else {
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
}
}
間接會(huì)調(diào)用activity的onSaveInstanceState方法
protected void onSaveInstanceState(Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
if (mAutoFillResetNeeded) {
outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
getAutofillManager().onSaveInstanceState(outState);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
這里很明顯會(huì)調(diào)用window的saveHierarchyState()方法來(lái)保存數(shù)據(jù)桐猬,在window中會(huì)讓mContentParent去分發(fā)數(shù)據(jù),最終都會(huì)調(diào)用view的onSaveInstanceState
這個(gè)也是OnSaveInstanceState的回調(diào)框喳,所以調(diào)用OnSaveInstanceState并不僅限于異常狀態(tài)推出的情況才會(huì)調(diào)用了课幕,當(dāng)一個(gè)activity被stop之前就會(huì)去調(diào)用
當(dāng)然這都是原來(lái)activity存在的情況
而當(dāng)為null時(shí)厦坛,表明此activity對(duì)應(yīng)的進(jìn)程不在五垮,那有兩種情況,第一種是activity還沒(méi)有創(chuàng)建杜秸,自然是沒(méi)有的放仗,第二種是進(jìn)程沒(méi)有創(chuàng)建
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivityLocked(next, true, true);
會(huì)調(diào)用ActivityStackSupervisor類的startSpecificActivityLocked方法
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
可以看到首先用包名去拿進(jìn)程,有的話直接調(diào)用realStartActivityLocked方法撬碟,里面間接調(diào)用了scheduleLaunchActivity方法,當(dāng)然會(huì)間接調(diào)用
performLaunchActivity方法诞挨,來(lái)具體看下
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 (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
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) {
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);
}
}
這里調(diào)用了activity的onCreate方法莉撇,而在后面,如果沒(méi)有mFinished標(biāo)志的話惶傻,就說(shuō)明異常了棍郎,此時(shí)就會(huì)調(diào)用callActivityOnRestoreInstanceState方法,也就是OnRestoreInstanceState來(lái)進(jìn)行數(shù)據(jù)恢復(fù)(一般屏幕旋轉(zhuǎn)會(huì)調(diào)用此方法)
如果沒(méi)有進(jìn)程的話,就新開(kāi)啟進(jìn)程
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
此方法將通過(guò)socket發(fā)送消息給zygote
zygote將派生出一個(gè)子進(jìn)程银室,子進(jìn)程將通過(guò)反射調(diào)用ActivityThread的main函數(shù)
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");
}
這里就是新建主線程的looper涂佃,并且調(diào)用了 thread.attach(false);方法
也就是新建了Application對(duì)象
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
這里新建了新進(jìn)程的pid,然后調(diào)用了attachApplicationLocked方法
這方法主要做了兩件事,第一個(gè)是創(chuàng)建了application對(duì)象蜈敢,然后就是創(chuàng)建了要進(jìn)入的activity辜荠,具體看代碼
//ams
if (app.instr != null) {
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);
} else {
從而走到了ActivityThread的handleBindApplication方法
里面有幾點(diǎn)要說(shuō)下
//ActivityThread
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
創(chuàng)建了LoadedApk對(duì)象,所以一個(gè)app就一個(gè)loadedApk對(duì)象
里面存放著從xml解析的各種服務(wù)抓狭,廣播伯病,對(duì)象的list,還有包名等信息
當(dāng)然還創(chuàng)建了ContextImpl對(duì)象
final ContextImpl appContext =
ContextImpl.createAppContext(this, data.info);
...
try {
java.lang.ClassLoader cl = getClassLoader();
if (!mPackageName.equals("android")) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"initializeJavaContextClassLoader");
initializeJavaContextClassLoader();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
并且用反射新建了Application對(duì)象否过,里面調(diào)用了attach方法
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
而我們常調(diào)用的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
也是由mInstrumentation創(chuàng)建的午笛。
可以說(shuō)如果看完了此篇文章,上面的幾個(gè)問(wèn)題自然也就引刃而解了