Intent.FLAG_ACTIVITY_CLEAR_TOP与SingleTask的区别

起因

在测试Activity的启动过程中,测试Intent.FLAG_ACTIVITY_CLEAR_TOP以及SingleTask的过程中发现这两者有一些区别。

实验条件

准备了4个Activity,分别为:MainActivitySecondActivityThirdActivityFourthActivity

启动顺序为: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。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券