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。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容