Android:launchMode
用于指定Activity被启动的方式,主要包括两个方面:即Activity是否为单实例,及Activity归属的task。不管是那种方式,被启动的Activity都要位于Activitytask的栈顶。
1),standard,默认状态,这种模式下Activity是多实例的,系统总是启动一个新的Activity来满足要求,即使之前已经存在这个Activity的实例;并且它归属于调用startactivity将其启动那个task(除非intent明确指明FLAG_ACTIVITY_NEW_TASK,这样就跟singleTask的启动模式是一样的)。
2),singletop,这个跟standard模式非常类似,它也表明Activity是多实例(下面是例外的情况)的,且task的归属也一致。区别是:
对于standard,无论何时它都会生成一个新的Activity实例;而singleTop当遇到目标Activity已经存在与目标task的栈顶时,会将Intent通过onNewIntent传给这个Activity而不是生成一个新的实例。
3),singleTask,它表明这个Activity是单实例的,Intent将通过OnNewIntent传送给已有的实例;而且他总是在一个新的task中启动。这种类型的Activity永远在task的根位置。另外,singleTask允许其他的Activity进驻到它所在的task中,这一点跟singleInstance不同。
4),singleInstance,和singleTask基本一致,不过它不允许其他的Activity进驻到它所属的task中,也就是说,singleInstance永远都是在一个孤立的task中。
Activity的生命周期
一个activity的启动:
10-26 22:18:23.365 24691-24691/? D/First-Activity: recycle,,onCreate
10-26 22:18:23.365 24691-24691/? D/First-Activity: recycle,,onStart
10-26 22:18:23.367 24691-24691/? D/First-Activity: recycle,,onResume
按back键,让activity的退出,activity会被出栈(Activitystack):
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onPause
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onStop
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onDestroy
按home间,让activity退出,会执行onPause(),onStop(),但是不会执行onDestory(),
启动另一个activity:
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onPause
com.firstapp.linjw.myapplication_n D/Second-Activity: recycle,,onCreate
com.firstapp.linjw.myapplication_n D/Second-Activity: recycle,,onStart
com.firstapp.linjw.myapplication_n D/Second-Activity: recycle,,onResume
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onStop
从第二个activity返回:
com.firstapp.linjw.myapplication_n D/Second-Activity: recycle,,onPause
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onRestart
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onStart
com.firstapp.linjw.myapplication_n D/First-Activity: recycle,,onResume
com.firstapp.linjw.myapplication_n D/Second-Activity: recycle,,onStop
com.firstapp.linjw.myapplication_n D/Second-Activity: recycle,,onDestroy
1,ActivityManagerService的功能
,ActivityManagerService的功能
1)组件状态的管理,四个组件的开启、关闭等一系列操作
2)组件状态查询,查询组件当前的运行情况
3)Task相关的操作,removeTask,movetasktofront。
4)其他一些系统运行信息的查询,getMemeoryInfo等。
AMS是在systemserver中启动的。
SystemServer.java
private void startBootstrapServices() {
//这里会调用AMS的start方法。
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
//然后,进行初始化,并把一些服务添加到serviceManager中。
mActivityManagerService.initPowerManagement();
mActivityManagerService.setSystemProcess();
mActivityManagerService.installSystemProviders();
mActivityManagerService.setWindowManager(wm);
mActivityManagerService.enterSafeMode();
//将一系列与进程管理相关的服务,注册到systemmanager。
mActivityManagerService.setSystemProcess();
//下面这个调用会先执行AMS中的systemready方法,确保AMS启动ok了,才会执行这个回调,在这个回调中,systemserver接着执行系统服务的启动,在这里启动systemUI。
mActivityManagerService.systemReady(new Runnable() {
public void run() {
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
mActivityManagerService.startObservingNativeCrashes();
startSystemUi(context);
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
}
});
}
ActivityManagerService.java
public void systemReady(final Runnable goingCallback) {
//在AMS启动完成之前, mSystemReady是false的,
synchronized(this) {
if (mSystemReady) {
goingCallback.run();
return;
}
mSystemReady = true;
}
//下面是AMS的启动操作,包括启动home应用程序。
retrieveSettings();
readGrantedUriPermissionsLocked();
…
//这里去执行systemserver中的回调,继续systemserver中未完成的系统服务的启动。因为systemserver的后续运行要依赖AMS,所以在AMS还没就绪的情况下就冒然返回,可能造成系统宕机。
if (goingCallback != null) goingCallback.run();
...
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
startHomeActivityLocked(currentUserId, "systemReady");
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
启动时,通过Lifecycle这个Systemservice先创建ActivityManagerService实例,然后调用其start方法。
在AMS的构造函数中,会创建一个线程ServiceThread,这是一个自带消息队列的线程。
ActivityManagerService,一个用于管理Activity(其他组件)运行状态的系统进程。
AMS会向servicemanager登记多种Binderserver,如:activity,meminfo,cpuinfo,processinfo,permission等。
public void setSystemProcess() @ActivityManagerService.java{
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this));
ServiceManager.addService("cpuinfo", new CpuBinder(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
ServiceManager.addService("permission", new PermissionController(this));
}
2,管理当前系统中的Activity状态。
Activitystack是管理系统中所有Activity状态的一个数据结构。一个Activity所经历的状态有:
enum ActivityState {
INITIALIZING,//正在初始化
RESUMED,//恢复
PAUSING,//正在暂停
PAUSED,//已经暂停
STOPPING,//正在停止
STOPPED,//已经停止
FINISHING,//正在完成
DESTROYING,//正在销毁
DESTROYED//已经销毁
}
Activity的状态迁移图:
的状态迁移图:
2.1 AMS主要的变量
ActivityManagerService.java
AMS通过ActivityStackSupervisor mStackSupervisor管理系统的Activitystack,通过StackSupervisor运行所有的activitystacks。
ActivityRecord mFocusedActivity;//当前拥有焦点的Activity。
RecentTasks mRecentTasks;//用于启动最近任务的intent列表。
ActivityStackSupervisor.java
ActivityStack mHomeStack;//包含launcher app的stack,
ActivityStack mFocusedStack;//当前可以接收输入事件或启动下一个Activity的stack。
//等待即将可见的新的Activity的列表。
ArrayList mWaitingVisibleActivities;
//列表中的Activity可以被stop,但是要等待下一个Activity就绪。
ArrayList mStoppingActivities
//列表中Activity可以被finish的,但是要等上一个Activity就绪。
ArrayList mFinishingActivities
ActivityStack.java
//所有前面Activity的回退记录,包括可能正在运行的Activity。
ArrayList mTaskHistory
//正在运行的Activity的列表,以最近的使用情况排序,第一个是最近最少使用的元素。
ArrayList mLRUActivities
//当前正在被暂停的Activity
ActivityRecord mPausingActivity
//上一个被暂停的Activity
ActivityRecord mLastPausedActivity
//当前被恢复的Activity
ActivityRecord mResumedActivity
//最近一次被启动的Activity
ActivityRecord mLastStartedActivity
TaskRecord.java
//task中的所有的Activity,这个task是在历史记录中按顺序排列的
ArrayList mActivities;
//当前的stack,管理者这个task中的Activity。
ActivityStack stack;
ActivityRecord.java
//表明这个Activity所属的task,
TaskRecord task;
大致结构:
mStackSupervisor(ActivityStackSupervisor)负责管理所有的Activitystack。
ActivityStack管理着系统中的task,也就是TaskRecord。
TaskRecord中的mActivities中保存了属于当前task的Activitys(ActivityRecord),这些Activity在是以stack的形式存放的,每一个Activity就是一个Activityrecord。
从获取顶层Activity的函数可以看出以上关系:
final ActivityRecord topRunningActivityLocked()@ActivityStack.java{
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
}
}
ActivityRecord topRunningActivityLocked()@TaskRecord.java{
for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord r = mActivities.get(activityNdx);
if (!r.finishing && stack.okToShowLocked(r)) {
return r;
}
}
}
因为Task是有先后之分的,所以对ActivityRecord的存储使用的是stack栈的方式,具体可以参考addActivityAtBottom()@TaskRecord.java,addActivityToTop()@TaskRecord.java
3,startActivity的过程
直接从AMS说起:
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());
}
通过UserHandle.getCallingUserId()获取调用者的用户ID。
//下面主要权限检查
public final int startActivityAsUser(...){
//调用者是否属于被隔离的对象。
enforceNotIsolatedCaller("startActivity");
//调用者是否有权限执行这一操作。
userId = mUserController.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(),userId, false, ALLOW_FULL_ONLY, "startActivity",
null);
return mActivityStarter.startActivityMayWait(…);
}
final int startActivityMayWait(...)@ActivityStarter.java{
//通过解析intent,确定目标Activity。
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
profilerInfo);
//判断目标Activity所属进程,是不是重量级进程,对于重量级进程不参与正常的应用程序的生命周期。所以如果系统中已经存在的重量级进程不是即将要启动的这个,那么要给intent重新赋值,重新解析。
if (aInfo.applicationInfo.privateFlags&
ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0)
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
final ProcessRecord heavy = mService.mHeavyWeightProcess;
if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
|| !heavy.processName.equals(aInfo.processName))) {
Intent newIntent = new Intent();
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
new IntentSender(target));
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
newIntent.setClassName("android",
HeavyWeightSwitcherActivity.class.getName());
intent = newIntent;
rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/,
userId);
}
}
//调用 startActivityLocked进一步执行启动操作。这个 startActivityLocked函数参数较多,后面还有调用同名的 startActivityLocked函数,它的参数较少。
int res = startActivityLocked(…);
}
final int startActivityLocked(...)@ActivityStarter.java{
//确保调用者本身的进程是存在的,否则返回 PERMISSION_DENIED,权限被拒绝错误。
ProcessRecord callerApp = null;
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
}else{
err = ActivityManager.START_PERMISSION_DENIED;
}
//处理标记: FLAG_ACTIVITY_FORWARD_RESULT,即Activity_result的跨越式传递。
if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
&& sourceRecord != null) {
resultWho = sourceRecord.resultWho;
}
//再次对调用者做权限检查,包括是否匹配intent-filter规则。
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo,
resultWho,requestCode, callingPid, callingUid, callingPackage,…);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
//生成一个ActivityRecord,记录各项判断结果。
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid,
callingPackage,…);
//调用 startActivityUnchecked,处理启动模式,及intent标志相关的。
err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags,true, options, inTask);
}
//对一系列启动标志的处理。
对一系列启动标志的处理。
private int startActivityUnchecked(...){
//获取intent中的启动标记。
final Intent baseIntent = mInTask.getBaseIntent();
mLaunchFlags = mLaunchFlags |baseIntent.getFlags();
//如果被启动的对象和调用者是同一个,什么都不用做,只要正确恢复顶层的Activity。
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
resumeTargetStackIfNeeded();
return START_RETURN_INTENT_TO_CALLER;
}
//要启动的是newtask,相关的处理。
if(mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0){
newTask = true;
setTaskFromReuseOrCreateNewTask(taskToAffiliate);
}
//接着调用另一个startActivityLocked。
mTargetStack.startActivityLocked(mStartActivity, newTask,
mKeepCurTransition, mOptions);
//恢复最上层的Activity。
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack,
mStartActivity,mOptions);
}
//这是启动Activity的最后一步了。
final void startActivityLocked(){
//如果目标Activity不在新的task中启动,就要找到他属于那个已存在的task,通过遍历整个 mTaskHistory列表,如果整个task对用户还不可见,先把Activity加进去,并把它加到history队列中。addConfigOverride(r, task);这句调用是在WindowManagerservice中做好注册,也就是添加一个AppWindowToken,
if (!newTask) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
if (task == r.task) {
task.addActivityToTop(r);
r.putInHistory();
addConfigOverride(r, task);
}
}
}
//是否显示启动窗口。
if (SHOW_APP_STARTING_PREVIEW && doShow) {
ActivityRecord prev =
r.task.topRunningActivityWithStartingWindowLocked();
r.showStartingWindow(prev, showStartingIcon);
}
}
到这里startActivity的一系列调用就分析完了,接下来就是恢复最顶层的Activity。
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions
targetOptions)@ActivityStackSupervisor.java {
targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
result = resumeTopActivityInnerLocked(prev, options);
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev,
ActivityOptions options) {
//取出最上面有效的Activity。
final ActivityRecord next = topRunningActivityLocked();
//next为null,启动launcher界面。
if (next == null) {
return isOnHomeDisplay() &&
mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);
}
//如果正在运行的Activity就是目标对象,就不用重复启动了。
if (mResumedActivity == next && next.state == ActivityState.RESUMED){
return false;
}
//如果目标Activity正在等待停止,就是正在stoping,那么就终止这个操作,从一下列表中移除,并置sleeping标志为false。
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);
//mResumedActivity不为null,说明前一个Activity还在运行,先执行pause操作。
if (mResumedActivity != null) {
pausing |= startPausingLocked(userLeaving, false, next,
dontWaitForPause);
}
//在启动新的Activity之前,要把前一个窗口隐藏掉。这个操作只在前一个Activity正在finishing时执行,这就意味着它处于正在resumed的Activity的上面,所以要把它尽快隐藏,也就是说是否要隐藏前一个取决于新的Activity是不是全屏显示。
if (prev != null && prev != next) {
if (prev.finishing) {
mWindowManager.setAppVisibility(prev.appToken, false);
}
}
//正式启动目标Activity,目标进程已有实例存在,告知目标线程resume指定的Activity,这个函数 scheduleResumeActivity会叫起Activity的onResume方法。
if (next.app != null && next.app.thread != null) {
mWindowManager.setAppVisibility(next.appToken, true);
next.app.thread.scheduleResumeActivity(next.appToken,
next.app.repProcState,mService.isNextTransitionForward(),
resumeAnimOptions);
}else{
//目标Activity所属程序还没进程在运行,启动目标进程。
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
}
// startSpecificActivityLocked最后会调用Process.start()启动一个进程,同时加载了 ActivityThread这一主线程。
private final void startProcessLocked(...)@ActivityManagerService.java{
entryPoint = "android.app.ActivityThread";
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
}
//目标进程启动后,会通过 attachApplication回调AMS,
private void attach(boolean system)@ActivityThread.java {
final IActivityManager mgr = ActivityManagerNative.getDefault();
mgr.attachApplication(mAppThread);
}
//AMS在接收回调后,会判断当前是否有Activity等待这个进程的启动,如果有,就调用 realStartActivityLocked继续之前的启动
操作,接下来就是Activity生命周期的开始。
private final boolean attachApplicationLocked()@ActivityManagerService.java{
mStackSupervisor.attachApplicationLocked(app);
}
boolean attachApplicationLocked(ProcessRecord app)@ActivityStackSupervisor.java{
realStartActivityLocked(hr, app, true, true);
}
final boolean realStartActivityLocked()@ActivityStackSupervisor.java{
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,…);
}