页面跳转的时候,假如说之前已经有这个页面了,再次生成这个页面好像有点傻傻的,为什么不直接用前面已经生成的那个页面呢。这就要说到activity的启动模式。
android四种launchMode
AndroidManifest里设计了四种启动模式,分别是:
- standard
- singleTop
- singleTask
- singleInstance
standard 标准模式
默认的启动模式,如果不在Manifest.xml里面为某个activity指定android:launchMode,那个就默认是standard。这种模式下,每次都会创建新的实例。
这种模式下,谁启动了这个activity,那么这个Activity就运行在启动它的那个activity所在的栈中。
以Demo来举例,假如说有A,B,C三个Activity(其中A是MainActivity),顺序是A -> B -> C -> A,他们之前的跳转都使用startActivity(new Intent(xxx,xxx)),且不调用finish。
那么这个过程中任务栈是这样的:
每次都是新生成一个实例。
如果在最后一个图之后,按下硬件的后退键,那么呈现的顺序就是从上到下的。
新建一个工程,让MainActivity的启动模式为standard,有个按钮按一下就启动MainActivity自己
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.bt_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, MainActivity.class);
startActivity(intent);
}
});
}
程序启动后,按两下按钮。照理说现在栈里面应该有3个MainActivity实例。想个方法来验证一下
在终端里面执行命令adb shell dumpsys activity
,打印出来很多信息,只要看下面一小段就行。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #162
TaskRecord{43d73e70 #162 A=jean.test.testtaskaffinity U=0 sz=3}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #2: ActivityRecord{4331abe8 u0 jean.test.testtaskaffinity/.MainActivity t162}
Intent { cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{43b92e90 585:jean.test.testtaskaffinity/u0a472}
Hist #1: ActivityRecord{43f9e0d0 u0 jean.test.testtaskaffinity/.MainActivity t162}
Intent { cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{43b92e90 585:jean.test.testtaskaffinity/u0a472}
Hist #0: ActivityRecord{43f67ba8 u0 jean.test.testtaskaffinity/.MainActivity t162}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=jean.test.testtaskaffinity/.MainActivity bnds=[540,1215][804,1494] }
ProcessRecord{43b92e90 585:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{43d73e70 #162 A=jean.test.testtaskaffinity U=0 sz=3}
Run #2: ActivityRecord{4331abe8 u0 jean.test.testtaskaffinity/.MainActivity t162}
Run #1: ActivityRecord{43f9e0d0 u0 jean.test.testtaskaffinity/.MainActivity t162}
Run #0: ActivityRecord{43f67ba8 u0 jean.test.testtaskaffinity/.MainActivity t162}
从上面的信息可以知道,现在有两个任务栈,名字分别是com.huawei.android.launcher
(桌面)和jean.test.testtaskaffinity
(本文的示例程序)。
看到com.huawei.android.launcher
这个栈里面只有一个Activity,就是桌面
看到jean.test.testtaskaffinity
这个栈里面有三个Activity,都是MainActivity的实例
singleTop 栈顶复用
这种启动模式,会判断当前栈顶的Activity是不是要启动的Activity,如果是,则不创建新的而是直接引用这个Activity,如果不是,则创建新的Activity。
假如说有A,B,C三个Activity,每个都设置了android:launchMode="singleTop"
,那么结果如下,看上去和上面的standard好像没什么不同。
但是,如果让B跳转到C的时候顺便finish自己,C跳转到A的时候顺便finish自己,那么结果如下:
C跳转到A需要启动A的时候,顺便finish了自己,由于A是singleTop模式,系统判断它是当前栈顶,则不生成新的Activity.
同样是上面那个程序,把MainActivity的启动模式改成android:launchMode="singleTop"
,点两次按钮,打印出来的信息如下:
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #166
TaskRecord{43ffeb98 #166 A=jean.test.testtaskaffinity U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #0: ActivityRecord{438651d0 u0 jean.test.testtaskaffinity/.MainActivity t166}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{43a7fdb0 28936:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{43ffeb98 #166 A=jean.test.testtaskaffinity U=0 sz=1}
Run #0: ActivityRecord{438651d0 u0 jean.test.testtaskaffinity/.MainActivity t166}
看到jean.test.testtaskaffinity
这个栈里面只有一个MainActivity的实例,验证了上面singleTop的说法。
singleTask
系统首先会检查是否存在想要的任务栈,若没有则创建该任务栈并创建activity实例并压入,若有这个任务栈,再检查这个栈里面是否有该Activity的实例,若没有则创建并压入,若有则清除其上的所有activity,让其置顶。
假如说有A,B,C三个Activity,只有A设置了android:launchMode="singleTask"
,其他都是默认的standard,那么结果如下,从C跳转到A的时候,由于A是singleTask,系统会检测栈中是否有A,如果有A则销毁A之上的其他Activity。
同样是上面那个程序,把MainActivity的启动模式改成android:launchMode="singleTask"
,点两次按钮,打印出来的信息如下:
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #169
TaskRecord{43358550 #169 A=jean.test.testtaskaffinity U=0 sz=1}
Intent { cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #0: ActivityRecord{44794e10 u0 jean.test.testtaskaffinity/.MainActivity t169}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{4335bbb8 26353:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{43358550 #169 A=jean.test.testtaskaffinity U=0 sz=1}
Run #0: ActivityRecord{44794e10 u0 jean.test.testtaskaffinity/.MainActivity t169}
看到jean.test.testtaskaffinity
这个栈里面只有一个MainActivity的实例
下面对这个程序,稍微做点儿变化,改成从MainAcvitity->TwoActivity->ThreeActivity->MainActivity
。这几个Activity都是singleTask
模式。
1.首先看从MainAcvitity->TwoActivity
的任务栈情况
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #177
TaskRecord{4467dde8 #177 A=jean.test.testtaskaffinity U=0 sz=2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #1: ActivityRecord{43306890 u0 jean.test.testtaskaffinity/.TwoActivity t177}
Intent { cmp=jean.test.testtaskaffinity/.TwoActivity }
ProcessRecord{44004b48 8314:jean.test.testtaskaffinity/u0a472}
Hist #0: ActivityRecord{445b87e8 u0 jean.test.testtaskaffinity/.MainActivity t177}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{44004b48 8314:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{4467dde8 #177 A=jean.test.testtaskaffinity U=0 sz=2}
Run #1: ActivityRecord{43306890 u0 jean.test.testtaskaffinity/.TwoActivity t177}
Run #0: ActivityRecord{445b87e8 u0 jean.test.testtaskaffinity/.MainActivity t177}
可以看到,当启动singleTask模式的TwoActivity的时候,系统首先会检查是否存在想要的任务栈(jean.test.testtaskaffinity),此时有这个任务栈,则再检查这个栈里面是否有TwoActivity的实例,没有,则创建并压入。
2.再看TwoActivity->ThreeActivity
原理和上一步是一样的。可以看到现在站里面从底层到上层分别是MainActivity、TwoActivity、ThreeActivity
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #177
TaskRecord{4467dde8 #177 A=jean.test.testtaskaffinity U=0 sz=3}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #2: ActivityRecord{43cfefa0 u0 jean.test.testtaskaffinity/.ThreeActivity t177}
Intent { cmp=jean.test.testtaskaffinity/.ThreeActivity }
ProcessRecord{44004b48 8314:jean.test.testtaskaffinity/u0a472}
Hist #1: ActivityRecord{43306890 u0 jean.test.testtaskaffinity/.TwoActivity t177}
Intent { cmp=jean.test.testtaskaffinity/.TwoActivity }
ProcessRecord{44004b48 8314:jean.test.testtaskaffinity/u0a472}
Hist #0: ActivityRecord{445b87e8 u0 jean.test.testtaskaffinity/.MainActivity t177}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{44004b48 8314:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{4467dde8 #177 A=jean.test.testtaskaffinity U=0 sz=3}
Run #2: ActivityRecord{43cfefa0 u0 jean.test.testtaskaffinity/.ThreeActivity t177}
Run #1: ActivityRecord{43306890 u0 jean.test.testtaskaffinity/.TwoActivity t177}
Run #0: ActivityRecord{445b87e8 u0 jean.test.testtaskaffinity/.MainActivity t177}
3.再看ThreeActivity->MainActivity
。按照singleTask原理,系统里面有MainActivity需要的栈,且栈中有实例,则应该清除该实例之上的所有activity。
打印结果如下,印证了上面的推理过程。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #177
TaskRecord{4467dde8 #177 A=jean.test.testtaskaffinity U=0 sz=1}
Intent { cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #0: ActivityRecord{445b87e8 u0 jean.test.testtaskaffinity/.MainActivity t177}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{44004b48 8314:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{4467dde8 #177 A=jean.test.testtaskaffinity U=0 sz=1}
Run #0: ActivityRecord{445b87e8 u0 jean.test.testtaskaffinity/.MainActivity t177}
singleInstance
singleInstance这种启动模式和使用浏览器工作原理类似。在多个程序中访问浏览器时,如果当前浏览器没有打开,则打开浏览器,否则会在当前打开的浏览器中访问。申明为singleInstance的Activity会出现在一个新的任务栈中,而且该任务栈只存在这一个Activity。这种启动模式常用于需要与程序分离的界面。
假如说有A,B,C三个Activity,只有B设置了android:launchMode="singleInstance",其他都是默认的standard,那么结果如下,
当在最后一个图之后按硬件的后退键,那么呈现的顺序是B -> A -> C ->A -> 退出应用
。
图里面的结果也可以用adb shell dumpsys activity
来验证
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jean.test.testtaskaffinity">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".TwoActivity"
android:launchMode="singleInstance">
</activity>
<activity android:name=".ThreeActivity"
android:launchMode="standard">
</activity>
</application>
</manifest>
1.启动应用,此时仅存MainActivity
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #178
TaskRecord{43fcae10 #178 A=jean.test.testtaskaffinity U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #0: ActivityRecord{432fe9e0 u0 jean.test.testtaskaffinity/.MainActivity t178}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{4331f2f8 18019:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{43fcae10 #178 A=jean.test.testtaskaffinity U=0 sz=1}
Run #0: ActivityRecord{432fe9e0 u0 jean.test.testtaskaffinity/.MainActivity t178}
2.MAinActivity -> TwoActivity。可以看到此时多了一个任务栈,且里面只有TwoActivity的实例。
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #179
TaskRecord{44199180 #179 A=jean.test.testtaskaffinity U=0 sz=1}
Intent { cmp=jean.test.testtaskaffinity/.TwoActivity }
Hist #0: ActivityRecord{44198f00 u0 jean.test.testtaskaffinity/.TwoActivity t179}
Intent { cmp=jean.test.testtaskaffinity/.TwoActivity }
ProcessRecord{4331f2f8 18019:jean.test.testtaskaffinity/u0a472}
Task id #178
TaskRecord{43fcae10 #178 A=jean.test.testtaskaffinity U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #0: ActivityRecord{432fe9e0 u0 jean.test.testtaskaffinity/.MainActivity t178}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{4331f2f8 18019:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{44199180 #179 A=jean.test.testtaskaffinity U=0 sz=1}
Run #1: ActivityRecord{44198f00 u0 jean.test.testtaskaffinity/.TwoActivity t179}
TaskRecord{43fcae10 #178 A=jean.test.testtaskaffinity U=0 sz=1}
Run #0: ActivityRecord{432fe9e0 u0 jean.test.testtaskaffinity/.MainActivity t178}
3.TwoActivity-ThreeActivity
ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Stack #0:
Task id #2
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10600000 cmp=com.huawei.android.launcher/.Launcher }
Hist #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.huawei.android.launcher/.Launcher }
ProcessRecord{43b899d0 3967:com.huawei.android.launcher/u0a43}
Running activities (most recent first):
TaskRecord{43c35040 #2 A=com.huawei.android.launcher U=0 sz=1}
Run #0: ActivityRecord{437243f8 u0 com.huawei.android.launcher/.Launcher t2}
Stack #1:
Task id #178
TaskRecord{43fcae10 #178 A=jean.test.testtaskaffinity U=0 sz=2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
Hist #1: ActivityRecord{44052ac8 u0 jean.test.testtaskaffinity/.ThreeActivity t178}
Intent { flg=0x400000 cmp=jean.test.testtaskaffinity/.ThreeActivity }
ProcessRecord{4331f2f8 18019:jean.test.testtaskaffinity/u0a472}
Hist #0: ActivityRecord{432fe9e0 u0 jean.test.testtaskaffinity/.MainActivity t178}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=jean.test.testtaskaffinity/.MainActivity }
ProcessRecord{4331f2f8 18019:jean.test.testtaskaffinity/u0a472}
Task id #179
TaskRecord{44199180 #179 A=jean.test.testtaskaffinity U=0 sz=1}
Intent { cmp=jean.test.testtaskaffinity/.TwoActivity }
Hist #0: ActivityRecord{44198f00 u0 jean.test.testtaskaffinity/.TwoActivity t179}
Intent { cmp=jean.test.testtaskaffinity/.TwoActivity }
ProcessRecord{4331f2f8 18019:jean.test.testtaskaffinity/u0a472}
Running activities (most recent first):
TaskRecord{43fcae10 #178 A=jean.test.testtaskaffinity U=0 sz=2}
Run #2: ActivityRecord{44052ac8 u0 jean.test.testtaskaffinity/.ThreeActivity t178}
TaskRecord{44199180 #179 A=jean.test.testtaskaffinity U=0 sz=1}
Run #1: ActivityRecord{44198f00 u0 jean.test.testtaskaffinity/.TwoActivity t179}
TaskRecord{43fcae10 #178 A=jean.test.testtaskaffinity U=0 sz=2}
Run #0: ActivityRecord{432fe9e0 u0 jean.test.testtaskaffinity/.MainActivity t178}
注意:如果在一个singleTop或者singleInstance的Activity中通过startActivityForResult()方法来启动另一个Activity,那么系统会直接返回Activity.RESULT_CANCELED而不会再去等待返回。这是由于系统在Framework层做了对这两种启动模式的限制,因为Android开发者认为,不同Task之间,默认是不能传递数据的,如果一定要传递,那就只能通过Intent来绑定数据。
除了在AndroidManifest.xml里面可以通过给Activity设置android:launchMode来设置启动模式,还可以通过设置Intent的Flag来设置一个Activity的启动模式。(如果在AndroidManifest.xml和Intent里都设置了某个Activity的启动模式,则以Intent里的为准,即代码设置的优先级高于manifest里面的设置。)
有一些常用的Intent的Flag。这些flag是可以组合使用的,Intent有addFlag和setFlag两个方法来设置这些flag。
FLAG_ACTIVITY_NEW_TASK
使用一个新的task来启动一个Activity。
FLAG_ACTIVITY_SINGLE_TOP
使用singleTop模式来启动一个Activity.
FLAG_ACTIVITY_CLEAR_TOP
这个标识的作用是清除包含Activity的task中位于该Activity实例之上的其他Activity实例,效果等同于singleTask。
FLAG_ACTIVITY_NO_HISTORY
例如A启动B,B以这种模式启动C,C在启动D,则当前栈为ABD。即若Activity是以这种模式启动的,当该Activity启动其他Activity之后,该Activity就消失了。
FLAG_ACTIVITY_CLEAR_TASK
清除要启动的Activity所在的栈中的所有实例。一般是配合FLAG_ACTIVITY_NEW_TASK一起使用。
一般是在点击push消息需要进入应用的时候,Intent的这些flag有重要作用。
使用第三方push SDK,一般是在MainActivity里面进行绑定的。如果需要点击push消息,进入某个Activity。
如果是点击push消息,重新启动应用,那么设置如下:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK );
如果是点击push消息,进入指定的Activity,那么设置如下
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
TaskAffinity
上面使用adb shell dumpsys activity
打印了一些信息,里面有一些知识点和TaskAffinity有关。
TaskAffinity
即任务相关性。标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用包名。也可以由我们为每个Activity单独指定TaskAffinity
TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义。
任务栈分为前台任务栈和后台任务栈,后台任务栈中的Activity处于暂停状态。
moveTaskToFront
alwaysRetainTaskState
clearTaskOnLaunch
finishOnTaskLaunch
栈的管理
当应用长时间置于后台,系统可能会清理应用Task栈中的Activity,当用户返回应用保留的只有应用的启动Activity。通过以下设置改变这种行为!
alwaysRetainTaskState: 如果栈底Activity的这个属性被设置为true,Task中的所有activity将被长时间保存。
clearTaskOnLaunch:如果栈底activity的这个属性被设置为true,一旦用户离开Task, 则 Task栈中的Activity将被清空到只剩下栈底activity。这种情况刚好与 alwaysRetainTaskState相反。即使用户只是短暂地离开,task也会返回到初始状态 (只剩下栈底acitivty)。
finishOnTaskLaunch:与clearTaskOnLaunch相似,但它只对单独的activity起作用,而不是整个Task。它可以结束任何Activity,包括栈底的Activity。 当它设置为true时,当前的Activity只在当前会话期间作为Task的一部分存在, 当用户按下Home键重新点击图标启动应用,它将不存在。
参考
1.http://droidyue.com/blog/2015/08/16/dive-into-android-activity-launchmode/index.html
2.http://blog.csdn.net/liuhe688/article/details/6754323
3.http://blog.csdn.net/liuhe688/article/details/6761337