沉思曲:Activity启动
继上文之后,终于鼓起勇气来整理这篇文章了。说到Acitivity启动,其实是个复杂而艰难的过程,认真去分析这块可以发现很多意外的宝藏。本人才疏学浅,由工作分享所致不得不研究。
本文已代码为主,注释为辅,内容较长,烦请务必认真读完,相信必能有所获。先上图:
代码流程图
![](http://upload-images.jianshu.io/upload_images/1986354-dbb00910d4c3f038.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
就上图说明几点:
- 由于Activity启动过程中穿插着应用进程与AMS进程间的通信,上图中蓝色部分为进程的切换。
- 如图:中间为AMS进程,左边为源Activity所在进程,右边为目的Activity所在进程
note
- 为描述简单,考虑Activity **src **启动 Activity dest的过程。
- 将src所在的进程描述为客户端进程或源进程,将dest所在进程描述为目的进程。
- 文中提到的上文指的是:《梦幻曲:Android系统启动》
- 文中提到的AMS进程,指的是上文中的SystemServer进程。
源进程
1.1、先从StartActivity说起
- 当src调用startActivity(..)启动dest时,调用过程:
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
启动Activity传入Intent,Intent携带了src的Context信息,以及dest的Class信息或Action。
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
//请求码设为-1
startActivityForResult(intent, -1);
}
}
public void startActivityForResult(Intent intent, int requestCode) {
startActivityForResult(intent, requestCode, null);
}
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
//调用execStartActivity方法
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
//发送结果给src
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
} else {//嵌套Activity逻辑,现已不推荐使用了
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
startActivity方法还是比较简单:
- 调用startActivityForResut,requestCode为-1。
- 调用Instrumentation的execStartActivity方法,往下执行。
1.2、execStartActivity | Instrumentation.java
Instrumentation是啥?
1、一个应用与一个Instrumentation关联,该应用的每个Activity都有该Instrumentation的引用。
2、Instrumentation可理解为应用进程的管家,它负责管理应用端四大组件等(见后代码)。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
//IApplicationThread为Binder,AMS通过它来控制Activity生命周期等
IApplicationThread whoThread = (IApplicationThread) contextThread;
//查找列表,dest是否已启动,已启动则直接返回结果?
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
//AIDL调用服务进程AMS的startActivity方法
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
- 该方法通过Binder切换到AMS进程(即上文的SystemServer进程),交由AMS来处理。
- 这里注意传给startActivity的参数:whoThread,它的类型是IApplicationThread,它是AIDL接口。它传递的实例是contextThread,它的实际类型为ApplicationThread,继承Binder。AMS通过whoThread实现与应用进程的交互,从而控制应用进程中四大组件的生命周期。
- ActivityManagerService(AMS)负责四大组件的管理,AMS作为服务端运行在SystemServer进程中。客户端通过AIDL方式与AMS通信,这其中包括:
- 客户端调用ActivityManagerNative.getDefault(),获得AMS在客户端代理,通过该代理调用AMS提供的服务。
- AMS通过客户端传递的IApplicationThread对象来控制Activity的生命周期等。
为了后续分析方便,这里简要说下源进程与AMS是如何通信的:
源进程与AMS通信
- 源进程调用ActivityManagerNative.getDefault()获得AMS进程的Binder代理:ActivityManagerProxy
- 源进程通过Binder调用AMS方法
![](http://upload-images.jianshu.io/upload_images/1986354-5a9113c7bec752b0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
![](http://upload-images.jianshu.io/upload_images/1986354-67f4a9498a5060a1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/585)
AMS与源/目的进程通信
之所以加上目的进程,是因为启动的Activity可能与源Activity不在同一个进程中。
- AMS获得源/目的进程调用其方法是的入参Binder,如上方法中的whoThread
- 通过whoThread调用源/目的进程方法
![](http://upload-images.jianshu.io/upload_images/1986354-3c5e0af8862c4cda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/536)
AMS进程
2.1、startActivity
源进程调用了AMS的startActivity方法,传入whoThread等参数,该方法在ActivityManagerService.java中。
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
//调用startActivityAsUser方法
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode,
startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, true, "startActivity", null);
//调用ActivityStackSupervisor的startActivityMayWait方法
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}
2.2、startActivityMayWait
上面方法接着调用到startActivityMayWait,该方法在ActivityStackSupervisor.java中。
往下说之前,先插上一句:
ActivityStackSupervisior从类名可以看出,似乎是负责监督Activity栈的一个类。其实这个类类似于Instrumentation,把它理解为AMS的管家就可以了,只不过一个在源进程一个在AMS进程。
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
Bundle options, int userId) {
...
//备份,避免修改原始intent
intent = new Intent(intent);
/**
* 获取dest信息,判断是否有匹配的Component。
* 此处AMS通过Binder连接到PMS,由PMS负责Intent的匹配。
*/
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);
synchronized (mService) {
//AIDL通信,获取客户端进程pid等信息
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = Binder.getCallingPid();
callingUid = Binder.getCallingUid();
} else {
callingPid = callingUid = -1;
}
//获取处于前台的ActivityStack,即接收输入或正在启动下一Activity的Stack
final ActivityStack stack = getFocusedStack();
//配置是否发生变化
stack.mConfigWillChange = config != null
&& mService.mConfiguration.diff(config) != 0;
final long origId = Binder.clearCallingIdentity();
//设置了ApplicationInfo.FLAG_CANT_SAVE_STATE标志
//该标志表示:dest所在进程为重量级进程,此时不能按应用正常生命周期处理
if (aInfo != null &&
(aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
//dest的进程名等于其包名
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
//存在重量级进程正在运行,且该进程不是dest所要在的进程
//此时替换dest为HeavyWeightSwitcherActivity
if (mService.mHeavyWeightProcess != null &&
(mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
!mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
int realCallingUid = callingUid;
if (caller != null) {
//查找客户端进程信息
ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
realCallingUid = callerApp.info.uid;
} else {
ActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
IIntentSender target = mService.getIntentSenderLocked(
ActivityManager.INTENT_SENDER_ACTIVITY, "android",
realCallingUid, userId, null, null, 0, new Intent[] { intent },
new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent();
//是否返回结果
if (requestCode >= 0) {
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
}
//设置PendingIntent
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
new IntentSender(target));
//有Activity运行在该重量级进程中,假设为heavyActivity
if (mService.mHeavyWeightProcess.activities.size() > 0) {
ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
//设置dest的包名为heavyActivity包名
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
hist.packageName);
//设置dest的Task为heavyActivity所在Task
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
hist.task.taskId);
}
//heavyActivity不存在,设置新包名
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
newIntent.setFlags(intent.getFlags());
//将dest替换为HeavyWeightSwitcherActivity
newIntent.setClassName("android",
HeavyWeightSwitcherActivity.class.getName());
//设置新intent的信息
intent = newIntent;
resolvedType = null;
caller = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
componentSpecified = true;
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveIntent(
intent, null,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
aInfo = mService.getActivityInfoForUser(aInfo, userId);
} catch (RemoteException e) {
aInfo = null;
}
}
}
}
int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
callingPackage, startFlags, options, componentSpecified, null);
...
return res;
}
}
该方法可简述为:
- 判断是否有匹配的Activity
- 方法判断Intent是否设置了ApplicationInfo.FLAG_CANT_SAVE_STATE,如果设置了该标志,表示dest所在的进程为重量级进程,此时替换dest为HeavyWeightSwitcherActivity,改而启动HeavyWeightSwitcherActivity。
- HeavyWeightSwitcherActivity类似于启动选择器,当存在多个Activity满足启动的要求时,此时启动HeavyWeightSwitcherActivity,弹出选择界面,供用户选择要启动的Activity。
该方法最后调用了startActivityLocked方法。
2.3、startActivityLocked
该方法同样在ActivityStackSupervisor.java中。
final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {
int err = ActivityManager.START_SUCCESS;
ProcessRecord callerApp = null;
//判断AMS是否保存了源进程信息,并获取源进程pid、uid
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
err = ActivityManager.START_PERMISSION_DENIED;
}
}
if (err == ActivityManager.START_SUCCESS) {
final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
}
ActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null; //用来获取startActivityForeResult的结果
if (resultTo != null) {
//在task中查找src对应的ActivityRecord
sourceRecord = isInAnyStackLocked(resultTo);
if (sourceRecord != null) {
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}
//src所在的Activity堆栈
ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
int launchFlags = intent.getFlags();
//设置了Intent.FLAG_ACTIVITY_FORWARD_RESULT标志
//该标志表示:如果A->src->dest,则启动dest的结果返回给A,而不是src
if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
&& sourceRecord != null) {
//此时,src启动dest不得指定requestCode>=0
if (requestCode >= 0) {
ActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
//返回结果为src的返回结果
resultRecord = sourceRecord.resultTo;
//返回结果交给A
resultWho = sourceRecord.resultWho;
requestCode = sourceRecord.requestCode;
//将src的返回结果设为null,使src不处理
sourceRecord.resultTo = null;
if (resultRecord != null) {
resultRecord.removeResultsLocked(
sourceRecord, resultWho, requestCode);
}
}
//检查源进程是否有android.Manifest.permission.START_ANY_ACTIVITY权限
//检查源Activity是否具备目的Activity通过android:permission声明的权限
...
//为dest创建ActivityRecord
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified, this);
if (outActivity != null) {
outActivity[0] = r;
}
//获取处于前台的stack
final ActivityStack stack = getFocusedStack();
/**
* 前台stack中没有处于可见状态的Activity
* 或者前台可见Activity与src有不同的uid(不同app)
*/
if (stack.mResumedActivity == null
|| stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
//判断是否需要挂起目的Activity,比如正在通电话
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
PendingActivityLaunch pal =
new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
//挂起dest
mService.mPendingActivityLaunches.add(pal);
setDismissKeyguard(false);
ActivityOptions.abort(options);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
//运行切换,将运行切换时间置0,表示可任意切换app
if (mService.mDidAppSwitch) {
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true;
}
//先启动挂起等待的Activity
mService.doPendingActivityLaunchesLocked(false);
//接着往下执行
err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
...
return err;
}
该方法完成了:
- 检查Intent.FLAG_ACTIVITY_FORWARD_RESULT标志,获取接收结果Activity
- 检查源进程是否有android.Manifest.permission.START_ANY_ACTIVITY权限,通过PMS检查
- 检查目的Activity中的Permission权限,即声明Activity时的android:permission权限
- 如果某个组件设置了android:permission权限,那只有具备该权限的组件才能启动它。
- 如,Activity B设置了android:permission=”权限x”,那当其它组件其它B时,会检查该组件是否具有权限x,否则抛出异常SecurityException。
- 判断是否需要挂起目的Activity,如当前正在通话等。
- ActivityRecord封装了Activity相关信息,一个Activity对应一个ActivityRecord。
- ActivityStack就是平常说的Activity任务栈,其负责管理Activity,用来记录Activity启动的先后关系、状态信息等。
- 前台Activity:Activity在调用了其onStart()方法后,其就处于前台;前台可见:Activity在调用了其onResume()方法后。
2.4、startActivityUncheckedLocked
该方法在ActivityStackSupervisor.java中。
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
...
//若设置了Intent.FLAG_ACTIVITY_NO_USER_ACTION,则dest在onPause()之前不再调用其onUserLeaveHint()方法
mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
//dest是否需要延迟启动
if (!doResume) {
r.delayedResume = true;
}
//若设置了Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP,则AMS将dest作为其task的Top Activity
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
/**
* 若设置了ActivityManager.START_FLAG_ONLY_IF_NEEDED标志
* 判断src与dest是否是同一Activity,或者src是否为空;满足,则将top activity作为caller(即src)
*/
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
ActivityRecord checkedCaller = sourceRecord;
//src为空,将top activity作为src
if (checkedCaller == null) {
checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
}
//src与dest不同,清除ActivityManager.START_FLAG_ONLY_IF_NEEDED标志
if (!checkedCaller.realActivity.equals(r.realActivity)) {
startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
}
}
/**
* 判断是否需要为目的Activity分配新的task,即为launchFlags置位Intent.FLAG_ACTIVITY_NEW_TASK。
* 注意:此处区分launchMode与launchFlages,launchMode是被启动Activity在AndroidManifest.xml中声明的;
* launchFlags是启动Activity希望启动的方式。
*/
if (sourceRecord == null) { //src为空,为dest分配新task
if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
} else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
//src启动模式为singleInstance,为dest分配新task
//src的task只能有src,dest只能另外分配task
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
} else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
//dest的启动模式为singleInstance或singleTask,为dest分配新task
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
final ActivityStack sourceStack;
if (sourceRecord != null) {
if (sourceRecord.finishing) {
//src正在销毁,src所处的task可能为空或即将销毁;避免盲目将dest放到src所处task,为dest分配新task
if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
//将src及其task置空
sourceRecord = null;
sourceStack = null;
} else {
sourceStack = sourceRecord.task.stack;
}
} else {
sourceStack = null;
}
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
/**
* 由于需要dest分配新task,而src又要求返回结果
* 此时为避免混乱,先取消返回结果,并将返回结果置空
*/
r.resultTo.task.stack.sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
}
...
//为dest查找可复用的task
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
...
}
if (r.packageName != null) {
...
//如果dest与task栈顶Activity相同,判断是否需要重新创建dest
if (top != null && r.resultTo == null) {
if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if (top.app != null && top.app.thread != null) {
//设置了这些标志位,不重新创建dest实例
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
top.task);
topStack.mLastPausedActivity = null;
if (doResume) {
//不重新创建dest实例,直接启动顶部dest实例
resumeTopActivitiesLocked();
}
....
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
}
}
} else {
//返回错误结果
...
return ActivityManager.START_CLASS_NOT_FOUND;
}
...
// 在新的task中启动dest
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
targetStack = adjustStackFocus(r);
moveHomeStack(targetStack.isHomeStack());
if (reuseTask == null) {
//在新task中启动
r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
null, true);
} else {
r.setTask(reuseTask, reuseTask, true);
}
newTask = true;
//设置了Intent.FLAG_ACTIVITY_TASK_ON_HOME,即把dest置于Home Actvity之上,即按back键从dest返回到home
if (!movedHome) {
if ((launchFlags &
(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
== (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
r.task.mOnTopOfHome = true;
}
}
}
//不在新task中启动dest
else if (sourceRecord != null) {
...
//dest之前启动过,清除task中dest之上的Activity,即clearTop启动模式
//如,启动前:A-dest-src,启动后:A-dest
if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
keepCurTransition = true;
if (top != null) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
top.deliverNewIntentLocked(callingUid, r.intent);
...
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
//dest之前启动过,将dest放栈顶。如,启动前:A-dest-src,启动后:A-src-dest
else if (!addingToTask &&
(launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
if (top != null) {
final TaskRecord task = top.task;
task.moveActivityToFrontLocked(top);
...
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
//为dest设置task
r.setTask(sourceTask, sourceRecord.thumbHolder, false);
}
//标准启动流程,创建dest实例,放在task栈顶
else {
targetStack = adjustStackFocus(r);
moveHomeStack(targetStack.isHomeStack());
ActivityRecord prev = targetStack.topActivity();
r.setTask(prev != null ? prev.task
: targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
null, true);
}
...
//调用该方法,接着往下执行
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
mService.setFocusedActivityLocked(r);
return ActivityManager.START_SUCCESS;
}
方法略长,该方法主要是检查dest的启动模式,判断是否需要给dest创建新task,以及dest如何放置在其task中。
- 检查Intent是否设置Intent.FLAG_ACTIVITY_NO_USER_ACTION标志
- 检查Intent是否设置Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP标志
- 检查Intent是否设置ActivityManager.START_FLAG_ONLY_IF_NEEDED标志
- 判断是否需要为目的Activity分配新的task,并判断是否有可复用的task。
- 为目的Activity设置task,并根据目的Activity的launchmode调整该Task中的Activity。
方法接着调用了ActivityStack的startActivityLocked方法。
2.5、startActivityLocked
该方法在ActivityStack.java中,从类名可看出:ActivityStack用来描述我们常说的Activity栈。
/**
* 注:为方便描述,将dest所在的task标记为DestTask
*/
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
//DestTask信息
TaskRecord rTask = r.task;
final int taskId = rTask.taskId;
//DestTask之前不存在
if (taskForIdLocked(taskId) == null || newTask) {
//DestTask放入已存在task列表中
insertTaskAtTop(rTask);
//将DestTask切换到前台
mWindowManager.moveTaskToTop(taskId);
}
TaskRecord task = null;
//DestTask之前存在,在已存在task列表中找到它
if (!newTask) {
boolean startIt = true;
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
task = mTaskHistory.get(taskNdx);
//找到了DestTask
if (task == r.task) {
/**
* DestTask不可见,此时只将dest置于DestTask顶部,而不启动它
* 当用户按下返回键时,再启动dest
*/
if (!startIt) {
//将dest置于DestTask顶部
task.addActivityToTop(r);
//使DestTask中Actvity数量加1
r.putInHistory();
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
r.userId);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
ActivityOptions.abort(options);
return;
}
break;
} else if (task.numFullscreen > 0) {
startIt = false;
}
}
}
//DestTask不处于前台,则dest在调用onPause()之前,不回调其onUserLeaving方法。
if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG,
"startActivity() behind front, mUserLeaving=false");
}
//DestTask
task = r.task;
//将dest放在DestTask顶部
task.addActivityToTop(r);
//使DestTask中Actvity数量加1
r.putInHistory();
//dest是否为DestTask的root activity(即位于栈底)
//如果DestTask是新task,那DestTask只有dest,则dest肯定是root activity
r.frontOfTask = newTask;
//如果DestTask是新task,或dest所在进程未运行,则显示启动预览窗口
if (!isHomeStack() || numActivities() > 0) {
...
}
...
if (doResume) {
//调用该方法,继续往下执行
mStackSupervisor.resumeTopActivitiesLocked();
}
}
- 注释已解释了大部分内容,该方法主要是找到dest所在的task:DestTask,并将dest放在DestTask的顶部,以及其它一些信息等。
- 该方法接着调用了ActivityStackSupervisor的resumeTopActivitiesLocked方法。
2.6、resumeTopActivitiesLocked
该方法在ActivityStackSupervisor.java中,又回到这里了,其实AMS就是在这几个类换来换去~
boolean resumeTopActivitiesLocked() {
return resumeTopActivitiesLocked(null, null, null);
}
//注意:上步中入参都为null
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
//targetStack为null,将targetStack设置为处于前台的Task
if (targetStack == null) {
targetStack = getFocusedStack();
}
boolean result = false;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
//查找处于前台的stack
if (isFrontStack(stack)) {
//前台stask与targetStack相同,即启动Activity所在task为前台task
if (stack == targetStack) {
//在dest所在的task中调用该方法,注意:入参都为null
result = stack.resumeTopActivityLocked(target, targetOptions);
} else {
//启动HomeActivity
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}
- 方法内容:判断目的Activity所在的Task是否为前台可见Task
- 是,启动目的Activity
- 否,启动HomeActivity,即启动Launcher进程了,感兴趣的可以去翻源码,大同小异。
2.7、resumeTopActivityLocked
该方法在ActivityStack.java中,又回到ActivityStack了……
//该方法确保当前task顶部的Activity是resumed状态的(前台可见状态)
final boolean resumeTopActivityLocked(ActivityRecord prev) {
return resumeTopActivityLocked(prev, null);
}
//注意:此处入参都为null
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
//当前task中栈顶Activity,即dest
ActivityRecord next = topRunningActivityLocked(null);
...
//当前栈不存在Activity,启动Launcher
if (next == null) {
ActivityOptions.abort(options);
return mStackSupervisor.resumeHomeActivity(prev);
}
next.delayedResume = false;
//dest已经处于前台可见状态,设置动画,直接返回
if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
mStackSupervisor.allResumedActivitiesComplete()) {
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
return false;
}
//nextTask为dest所在task,记为DestTask
final TaskRecord nextTask = next.task;
//入参是prev为null,所以prevTask为null
final TaskRecord prevTask = prev != null ? prev.task : null;
//prevTask为null,忽略
if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {
...
}
/**
* 手机处于休眠状态,且该task不存在可见状态的Activity,且该task顶部Activity处于暂停状态
* 设置动画,直接返回
*/
if (mService.isSleepingOrShuttingDown()
&& mLastPausedActivity == next
&& mStackSupervisor.allPausedActivitiesComplete()) {
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
ActivityOptions.abort(options);
return false;
}
//dest的user未启动,直接返回
if (mService.mStartedUsers.get(next.userId) == null) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
//从stop列表中移除dest
mStackSupervisor.mStoppingActivities.remove(next);
//从即将休眠列表中移除dest
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
//从等待显示列表中移除dest
mStackSupervisor.mWaitingVisibleActivities.remove(next);
next.updateOptionsLocked(options);
//当前正在暂停其他Activity,等该暂停操作完成
if (!mStackSupervisor.allPausedActivitiesComplete()) {
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
//该代码不执行,跳过
if (false) {
...
}
//暂停AMS中前台不可见的Stack中resumed activity,dest才能启动!
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
if (mResumedActivity != null) {
pausing = true;
startPausingLocked(userLeaving, false);
}
if (pausing) {
if (DEBUG_SWITCH || DEBUG_STATES)
//dest所在进程存在,设置其进程信息
if (next.app != null && next.app.thread != null) {
mService.updateLruProcessLocked(next.app, false, true);
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
//系统即将休眠,结束mLastNoHistoryActivity
if (mService.mSleeping && mLastNoHistoryActivity != null &&
!mLastNoHistoryActivity.finishing) {
requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
null, "no-history", false);
mLastNoHistoryActivity = null;
}
...
ActivityStack lastStack = mStackSupervisor.getLastStack();
//next(即dest)所在进程存在
if (next.app != null && next.app.thread != null) {
if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
//窗口管理器标记next可见
mWindowManager.setAppVisibility(next.appToken, true);
next.startLaunchTickingLocked();
//上个处于可见状态的Activity
ActivityRecord lastResumedActivity =
lastStack == null ? null :lastStack.mResumedActivity;
ActivityState lastState = next.state;
mService.updateCpuStats();
//将next状态更改为可见状态
next.state = ActivityState.RESUMED;
//将next设置为当前可见的Activity
mResumedActivity = next;
next.task.touchActiveTime();
//AMS将next所在task添加进最近红的task列表
mService.addRecentTaskLocked(next.task);
mService.updateLruProcessLocked(next.app, true, true);
updateLRUListLocked(next);
//获取窗口配置信息
boolean notUpdated = true;
if (mStackSupervisor.isFrontStack(this)) {
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
if (config != null) {
next.frozenBeforeDestroy = true;
}
notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
}
if (notUpdated) {
//dest配置在启动过程中发生了变化,结束启动
ActivityRecord nextNext = topRunningActivityLocked(null);
if (nextNext != next) {
mStackSupervisor.scheduleResumeTopActivities();
}
if (mStackSupervisor.reportResumedActivityLocked(next)) {
mNoAnimActivities.clear();
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return true;
}
if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
return false;
}
try {
//处理dest收到的ActivityResult
ArrayList<ResultInfo> a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
next.app.thread.scheduleSendResult(next.appToken, a);
}
}
//回调dest的onNewIntent方法
if (next.newIntents != null) {
next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
...
next.sleeping = false;
mService.showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
//进程存在,直接调用scheduleResumeActivity方法
next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
mService.isNextTransitionForward());
mStackSupervisor.checkReadyForSleepLocked();
}
...
} else {
...
/**
* dest所在的进程不存在
* 调用该方法启动进程,进程启动后,流程与scheduleResumeActivity相同
*/
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
return true;
}
- 该方法执行完后dest为可见状态。
- 该方法还有个重要的地方:
- dest进程不存在时,这个方法会为其创建进程,进而引发出ActivityThread创建等(这里留到下一篇文章细讲)。
- 为看的仔细点,假设dest所在进程不存在,则调用ActivityStackSupervisor的startSpecificActivityLocked方法
2.8、startSpecificActivityLocked
该方法在ActivityStackSupervisor.java中,这里导向了目的进程创建流程,标注加红,下一篇文章从这里开始哦!
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// 获取dest所在进程信息
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
/**
* dest所在进程存在
* 由于上个方法已经判断dest进程不存在,为啥此处仍有判断?
* 难道在此期间,dest进程可能被启动了?
*/
if (app != null && app.thread != null) {
try {
app.addPackage(r.info.packageName, mService.mProcessStats);
//调用该方法继续
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
}
/**
* dest进程不存在,调用该方法启动进程,该流程见《ActivityThrad分析》
* 后续仍会调用上realStartActivityLocked方法
*/
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
- 由于dest进程不存在,会调用AMS的startProcessLocked方法为dest创建新进程,这是另外一套流程了。
- 这里先跳过进程创建,从realStartActivityLocked继续分析。
2.9、realStartActivityLocked
该方法在ActivityStackSupervisor.java中。
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
...
//dest记录进程信息
r.app = app;
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
//将dest保存到ProcessRecord中
int idx = app.activities.indexOf(r);
if (idx < 0) {
app.activities.add(r);
}
...
//调用该方法启动
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration), r.compat,
app.repProcState, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
...
}
...
return true;
}
- 该方法调用了app.thread的scheduleLaunchActivity方法,app.thread是啥?其实就是开始传入的whoThread,即源进程的Binder代理;或者是新创建目的进程的Binder代理。从这里开始,从AMS进程且换到目的进程了。
- AMS进程通过app.thread实现控制应用进程Activity的生命周期。
scheduleLaunchActivity从方法名可以看出,要启动目的Acitivity了。
目的进程
3.1、scheduleLaunchActivity
该方法在ActivityThread.java中,为ActivityThread的内部类。
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
int procState, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;
r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;
r.startsNotResumed = notResumed;
r.isForward = isForward;
r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;
updatePendingConfiguration(curConfig);
//通过H handler发送LAUNCH_ACTIVITY消息
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
- H handler很熟悉嘛~
- H同样为ActivityThread的内部类,这里插句闲话:从翻看Android源码来看,无论是ActivityManagerService,还是ServiceManager,其都通过一个类似的AcitivityThread、ServerThread以及一个Handler来实现流程的把控。
3.2、handleMessage
该方法在H 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");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
//调用该方法
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
...
}
3.3、handleLaunchActivity
该方法在ActivityThread.java中
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
//调用该方法启动dest
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//该方法会调用dest的onResume方法
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
//暂停dest,因为dest不在前台
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
//Honeycomb之前版本需要保存状态
if (r.isPreHoneycomb()) {
r.state = oldState;
}
if (!r.activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onPause()");
}
}
...
r.paused = true;
}
} else {
//出错,结束dest
try {
ActivityManagerNative.getDefault()
.finishActivity(r.token, Activity.RESULT_CANCELED, null);
} catch (RemoteException ex) {}
}
}
- 该方法调用performLaunchActivity启动dest。
- 在启动Activity方法后,调用handleResumeActivity方法回调dest的onResume方法
这里分析下内部的两个重要调用方法:performLaunchActivity 、handleResumeActivity
3.4、performLaunchActivity ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
//dest包信息(packageInfo为LoadAPK对象)
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
//启动dest的Intent是否指定了启动组件
ComponentName component = r.intent.getComponent();
if (component == null) {
//intent未指定启动组件,查询与Intent匹配的Activity
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
//dest是否设置了targetActivity,设置了则启动targetActivity
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
//反射创建dest实例
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
/**
* dest所在Application已启动,则直接返回它
* 否则为dest创建Application,并回调该Appication的onCreate方法
*/
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
//为dest创建上下文环境
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
//设置到dest中
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
//回调dest的onCreate方法!!!
mInstrumentation.callActivityOnCreate(activity, r.state);
r.activity = activity;
r.stopped = true;
//调用dest的onStart()方法
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.state != null) {
//设置了state,调用dest的onRestoreInstanceState方法
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
//回调dest的onPostCreate()方法
mInstrumentation.callActivityOnPostCreate(activity, r.state);
...
}
}
r.paused = true;
mActivities.put(r.token, r);
}
...
return activity;
}
- 该方法在设置了dest的组件信息后,反射创建dest实例,并以此调用其onCreate、onStart、ononRestoreInstanceState(如果设置了state)、onPostCreate方法
3.5、handleResumeActivity
该方法在ActivityThread.java中。
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
boolean reallyResume) {
unscheduleGcIdler();
//调用dest的onResume方法
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r != null) {
final Activity a = r.activity;
...
if (!willBeVisible) {
try {
//aidl调用AMS方法,判断dest是否可见
willBeVisible = ActivityManagerNative.getDefault().willActivityBeVisible(
a.getActivityToken());
} catch (RemoteException e) {
}
}
//将dest所在窗口添加到WindowManager
if (r.window == null && !a.mFinished && willBeVisible) {
//获取dest所在窗口
r.window = r.activity.getWindow();
//获取窗口的DecorView
View decor = r.window.getDecorView();
//将DecorView设置不可见
decor.setVisibility(View.INVISIBLE);
//获取WindowManager
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
//将DecorView添加到WindowManager
wm.addView(decor, l);
}
} else if (!willBeVisible) {
//隐藏dest所在窗口
r.hideForNow = true;
}
// Get rid of anything left hanging around.
cleanUpPendingRemoveWindows(r);
//显示dest
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
...
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
//设置软键盘属性
l.softInputMode = (l.softInputMode
& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
| forwardBit;
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
//显示dest窗口下的DecorView
wm.updateViewLayout(decor, l);
}
}
...
}
...
if (reallyResume) {
try {
//通知AMS,dest已处于可见状态
ActivityManagerNative.getDefault().activityResumed(token);
} catch (RemoteException ex) {
}
}
} else {
try {
//出现异常,结束dest
ActivityManagerNative.getDefault()
.finishActivity(token, Activity.RESULT_CANCELED, null);
} catch (RemoteException ex) {
}
}
}
- 该方法回调了dest的onResume方法,并将dest所在窗口设置为可见。这就是为什么Acitivity在onResume才是可见的了~
总结
总算写完了,看到这里估计你也晕了~
不想写总结了,就这样吧,觉得可以就点个赞吧。