美文网首页
Intent.FLAG_ACTIVITY_CLEAR_TOP与S

Intent.FLAG_ACTIVITY_CLEAR_TOP与S

作者: None_Ling | 来源:发表于2019-08-07 16:39 被阅读0次

    起因

    在测试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。

    相关文章

      网友评论

          本文标题:Intent.FLAG_ACTIVITY_CLEAR_TOP与S

          本文链接:https://www.haomeiwen.com/subject/ydtodctx.html