Differences between Activity Start Mode SingleTask and Intent.FLAG_ACTIVITY_CLEAR_TOP

Keywords: Android Google

singleTask: In-stack multiplexing mode. In this mode, if the Activity exists on the stack, it will not recreate the instance but destroy all the activities on it (excluding itself), reuse the Activity and call its onNewIntent method. If the Activity does not exist, it will be created and stacked to the required Activity. Task stack.

Intent.FLAG_ACTIVITY_CLEAR_TOP: Destroy the target Activity and all activities above it, recreate the target Activity, and do not call the onNewIntent method.

Intent.FLAG_ACTIVITY_SINGLE_TOP: When the activity is on the top of the stack, it can be reused and directly onNewIntent.

Next, let's look at demo:

singleTask

In the Manifest file, we designate MainActivity as singleTask.

        <activity
            android:name=".MainActivity"
            android:configChanges="orientation"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity" />
        <activity android:name=".ThirdActivity"></activity>

Print stack information in each Activity's onCreate method:

    private String getTaskInfo(){
        StringBuilder builder = new StringBuilder();
        ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> taskInfos = am.getRunningTasks(10);
        for (ActivityManager.RunningTaskInfo task: taskInfos){
            builder.append("id= "+task.id+"\n");
            builder.append("description= "+task.description+"\n");
            builder.append("numActivityes= "+task.numActivities+"\n");
            builder.append("topActivity= "+task.topActivity+"\n");
            builder.append("baseActivity= "+task.baseActivity.toString()+"\n");
        }
        return builder.toString();
    }

Set a Button in MainActivity to start Second Activity:

Intent intent =new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);

Set a Button in Second Activity to start ThirdActivity:

Intent intent = new Intent(SecondActivity.this,ThirdActivity.class);
startActivity(intent);

Set a Button in Second Activity to start MainActivity and pass the message:

Intent intent = new Intent(ThirdActivity.this,MainActivity.class);
startActivity(intent);

MainActivity's onNewIntent method also prints stack information:

    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        String taskInfo = getTaskInfo();
        Log.e(TAG, "onNewIntent: "+taskInfo);
    }

Start app and see what's printed

The first thing to start is MainActivity.

MainActivity: onCreate: id= 1568
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    baseActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    id= 1559
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
    baseActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}

You can see that the number of activities in MainActivity's stack is numActivities equal to 1, and topActivity and baseActivity represent Activeness at the top and bottom of the stack.

Next, start Second Activity.

SecondActivity: onCreate: id= 1568
    description= null
    numActivityes= 2
    topActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.SecondActivity}
    baseActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    id= 1559
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
    baseActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}

You can see that the Activity in the stack changes to 2

Next, start ThirdActivity.

ThirdActivity: onCreate: id= 1568
    description= null
    numActivityes= 3
    topActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.ThirdActivity}
    baseActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    id= 1559
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
    baseActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}

Activity in the stack becomes 3,

Then we start MainActivity from ThirdActivity.

MainActivity: onNewIntent: id= 1569
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    baseActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    id= 1559
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
    baseActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}

We found that only the onNewIntent method was executed here, and no onCreate method was executed, indicating that MainActivity was taken, and only MainActivity remained in the stack. The other two activities were destroyed.

Intent.FLAG_ACTIVITY_CLEAR_TOP

Next, we remove the singleTask startup mode of MainActivity (default startup mode), and the code to start MainActivity in ThirdActivity is as follows:

Intent intent = new Intent(ThirdActivity.this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);

The previous steps remain unchanged. When we start MainActivity from ThirdActivity, the information printed is as follows:

MainActivity: onCreate: id= 1570
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    baseActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    id= 1559
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
    baseActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}

The onCreate method is executed, indicating that Main Activity has been recreated and that the other two Activities have been destroyed.

Intent.FLAG_ACTIVITY_CLEAR_TOP + Intent.FLAG_ACTIVITY_SINGLE_TOP

Let's modify the code in ThirdActivity:

Intent intent = new Intent(ThirdActivity.this,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

The printing results are as follows:

MainActivity: onNewIntent: id= 1571
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    baseActivity= ComponentInfo{com.example.hp.testtext/com.example.hp.testtext.MainActivity}
    id= 1559
    description= null
    numActivityes= 1
    topActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}
    baseActivity= ComponentInfo{com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity}

As you can see, when using Intent.FLAG_ACTIVITY_CLEAR_TOP + Intent.FLAG_ACTIVITY_SINGLE_TOP, the onNewIntent method is called and MainActivity is reused, indicating that they can achieve the same effect as singleTask.

summary

singleTask destroys the Activity above the target Activity and reuses the existing target Activity (call onNewIntent), but Intent.FLAG_ACTIVITY_CLEAR_TOP is destroyed along with the target Activity and then recreates the target Activity.

SingleTask is written in Manifest file. If you feel too heavy, you can use Intent.FLAG_ACTIVITY_CLEAR_TOP + Intent.FLAG_ACTIVITY_SINGLE_TOP to achieve the same effect as singleTask.

Posted by laura_richer on Thu, 03 Jan 2019 13:33:12 -0800