起因
在测试Activity的启动过程中,测试Intent.FLAG_ACTIVITY_CLEAR_TOP
以及SingleTask
的过程中发现这两者有一些区别。
实验条件
准备了4个Activity,分别为:MainActivity
,SecondActivity
,ThirdActivity
,FourthActivity
。
启动顺序为:MainActivity
--> SecondActivity
--> ThirdActivity
--> FourthActivity
--> SecondActivity
。
实验过程
在FourthActivity
启动SecondActivity
中测试Intent的Flag以及LaunchMode的影响结果。
第一种:在Intent中加入Intent.FLAG_ACTIVITY_CLEAR_TOP
测试结果
在加入了Intent.FLAG_ACTIVITY_CLEAR_TOP
的标识位之后:
- 仍然会先清理指定Activity(即
SecondActivity
)之上的Activity - 但是原来存在的Activity会先被清理掉,接着会创建一个新的Activity对象来替代
测试日志
E/MainActivity: MainActivity onResume...
E/MainActivity: MainActivity onPause...
// SecondActivity启动
E/SecondActivity: SecondActivity onResume...com.timmy.sotest.SecondActivity@e4c8987
E/SecondActivity: SecondActivity onPause...
E/ThirdActivity: ThirdActivity onResume...
E/SecondActivity: SecondActivity onStop...
E/ThirdActivity: ThirdActivity onPause...
E/FourthActivity: FourthActivity onResume...
// 开始启动SecondActivity,先把ThirdActivity销毁
E/ThirdActivity: ThirdActivity onStop...
E/ThirdActivity: ThirdActivity onDestroy...
// 再开始启动SecondActivity流程
E/FourthActivity: FourthActivity onPause...
// 销毁之前存在的SecondActivity
E/SecondActivity: SecondActivity onDestroy...com.timmy.sotest.SecondActivity@e4c8987
// 重新创建新的SecondActivity
E/SecondActivity: SecondActivity onResume...com.timmy.sotest.SecondActivity@9b9f44
// 最后销毁FourthActivity
E/FourthActivity: FourthActivity onStop...
E/FourthActivity: FourthActivity onDestroy...
第二种:LaunchMode设置为SingleTask
测试结果
在Manifest.xml中设置LaunchMode后:
- 同样会清理指定Activity(即SecondActivity)之上的Activity
- 而会使用原来的Activity,并不会销毁原来的Activity之后重新创建
测试日志
E/MainActivity: MainActivity onResume...
E/MainActivity: MainActivity onPause...
// SecondActivity启动
E/SecondActivity: SecondActivity onResume...com.timmy.sotest.SecondActivity@e4c8987
E/SecondActivity: SecondActivity onPause...
E/ThirdActivity: ThirdActivity onResume...
E/SecondActivity: SecondActivity onStop...
E/ThirdActivity: ThirdActivity onPause...
// FourthActivity启动
E/FourthActivity: FourthActivity onResume...
E/ThirdActivity: ThirdActivity onStop...
E/ThirdActivity: ThirdActivity onDestroy...
// 开始启动SecondActivity
E/FourthActivity: FourthActivity onPause...
E/SecondActivity: SecondActivity onRestart...
// 使用原来的SecondActivity
E/SecondActivity: SecondActivity onResume...com.timmy.sotest.SecondActivity@e4c8987
E/FourthActivity: FourthActivity onStop...
E/FourthActivity: FourthActivity onDestroy...
原因
在ActivityStarter.startActivityUnchecked
函数中,在找到要启动的Activity所保存的TaskRecord后,会来处理该标识位:
// 如果设置了FLAG_ACTIVITY_CLEAR_TOP,或者mLaunchSingleInstance,mLaunchSingleTask则会进入该逻辑
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
|| mLaunchSingleInstance || mLaunchSingleTask) {
// 首先获取复用的Activity所在的Task
final TaskRecord task = reusedActivity.getTask();
// 接着调用performClearTaskForReuseLocked来清理Task中的Activity
final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,
mLaunchFlags);
...
if (top != null) {
...
// 如果返回来ActivityRecord不为空,则回调onNewIntent函数
top.deliverNewIntentLocked(mCallingUid, mStartActivity.intent,
mStartActivity.launchedFromPackage);
}
}
在TaskRecord.performClearTaskForReuseLocked
函数中,会开始清理复用的Activity上方的Activity。
final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
int numActivities = mActivities.size();
// 开始遍历Task中所有的Activity,从顶往下遍历
for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
// 如果找到要启动的Activity的话
if (r.realActivity.equals(newR.realActivity)) {
// Here it is! Now finish everything in front...
final ActivityRecord ret = r;
for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
// 开始遍历要启动的Activity之上的Activity
r = mActivities.get(activityNdx);
if (r.finishing) {
continue;
}
// 调用finishActivityLocked开始清理Activity
if (mStack != null && mStack.finishActivityLocked(
r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
--activityNdx;
--numActivities;
}
}
// Finally, if this is a normal launch mode (that is, not
// expecting onNewIntent()), then we will finish the current
// instance of the activity so a new fresh one can be started.
// 接着判断当前Activity的LaunchMode如果是LAUNCH_MULTIPLE,也就是默认的LaunchMode,
// 并且没有FLAG_ACTIVITY_SINGLE_TOP的话,就开始调用finishActivityLocked来结束该Activity
if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
&& (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
&& !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
if (!ret.finishing) {
if (mStack != null) {
mStack.finishActivityLocked(
ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
}
return null;
}
}
return ret;
}
}
return null;
}
所以,到此就知道了如果LaunchMode
为默认的话,并且没有设置FLAG_ACTIVITY_SINGLE_TOP
则会把原来的Activity销毁,重新创建新的Activity。
网友评论