启动模式简介:
1. standard:
每次启动都会创建一个新的实例,一个任务栈可以有多个实例,每个实例也可以属于不同的任务栈
2. singleTop:
栈顶复用。如果活动在栈顶,再次想创建该活动,不会创建新的Activity,同时会回调onNewIntent,通过该函数可以获得请求的信息
3. singleTask:
栈内复用,这是一种单例模式。只要Activity在一个栈中存在,多次调用都不会重新创建实例,也会回调onNewIntent,分5种情况
a) 目前任务栈S1中有ABC,这个时候Activity D以singleTask模式请求启动,其所需要的任务栈为S2,由于S2和D的实例都不存在,所以先创建任务栈S2,然后再创建D的实例并将其入栈到S2,S1此时为ABC,S2为D
b) 目前任务栈S1中有ABC,D以singleTask模式请求启动,其所需要的任务栈为S1,由于S1已经存在,所以直接创建D的实例并将其入栈到S1,S1此时为ABCD
c) 目前任务栈S1中有ADBC,D以singleTask模式请求启动,其所需要的任务栈为S1,根据复用原则B和C出栈,D位于栈顶,此时S1为AD
4. singleInstance:
单实例模式。全局单例,当以singleInstance模式创建一个Activity时,会单独创建一个任务栈,然后在该任务栈中创建该Activity,该任务栈只能存在一个Activity
3个例子
3个Activity,分别为A、B、C
1. A为standard,B、C为singleTask
同时设置B、C的任务栈为com.example.sun.task1,A在默认任务栈
设默认任务栈为S1,设com.example.sun.task为S2
<activity android:name=".A"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".B" android:taskAffinity="com.example.sun.task1" android:launchMode="singleTask"/> <activity android:name=".C" android:taskAffinity="com.example.sun.task1" android:launchMode="singleTask"/>
启动顺序:A → B → C → A → B
退出顺序:B → A → 桌面(按两次返回键)
a) A → B → C:
启动A:A的taskAffinity继承自包名,创建默认任务栈(即S1),然后将在S1中创建A,S1为前台任务栈
启动B:根据singleTask的启动原则a点,因为没有任务栈S2,创建任务栈S2,然后创建B,
此时有两个任务栈S1,S2。因为此时运行B,S2为前台任务栈。
启动C:根据singleTask的启动原则b点,因为存在任务栈S2,直接创建任务栈S2,然后创建 C,
此时有两个任务栈S1,S2。因为此时运行C,S2为前台任务栈。如下图所示
在terminal输入adb shell dumpsys activity,找到Running activities
可以看到C,B在com.example.sun.task1(即S2)中,A在com.example.sun.webtest(即S1)中,其他不用管
b) A → B → C → A:
再启动A,因为是C启动A,并且A为standard,会把A创建在C的任务栈中,并位于栈顶
c) A → B → C → A → B:
从A中启动B,因为B为singleTask,不会创建新的实例,根据singleTask的原则c点,把A、C出栈
d) 退出顺序:B → A → 桌面
此时再按返回,B从S2中出栈,S2任务栈不存在了,此时只能切换到后台任务栈S1,显示A,
再次按返回键,A从从S1中出栈,就回到了桌面
2. A、B、C为singleTask
同时设置A的任务栈为com.example.sun.task1,BC的任务栈为com.example.sun.task2
设com.example.sun.task1任务栈为S1,com.example.sun.task2任务栈为S2
<activity android:name=".A"
android:taskAffinity="com.example.sun.task1"
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=".B"
android:taskAffinity="com.example.sun.task2"
android:launchMode="singleTask"/>
<activity android:name=".C"
android:taskAffinity="com.example.sun.task2"
android:launchMode="singleTask"/>
启动顺序:A → B → C → A → B
退出顺序:B → A → 桌面(按两次返回键)
这里结果是和上面一样的,但任务栈的内容不一样,因为A为singleTask,具体分析如下:
a) A → B → C:(基本和前面一样)
启动A:根据singleTask的启动原则a点,因为没有任务栈S1,创建任务栈S1,然后将在S1中创建A,S1为前台任务栈,
启动B:根据singleTask的启动原则a点,因为没有任务栈S2,创建任务栈S2,然后创建B,
此时有两个任务栈S1,S2。因为此时运行B,S2为前台任务栈。
启动C:根据singleTask的启动原则b点,因为存在任务栈S2,直接创建任务栈S2,然后创建 C,
此时有两个任务栈S1,S2。因为此时运行B,S2为前台任务栈,如下图所示
b) A → B → C → A:
再启动A,因为A为singleTask,不会把A创建在C的任务栈中,而是切换S1为前台任务,S2变为后台任务
c) A → B → C → A → B:
启动B,因为B为singleTask,根据singleTask的原则c点,把C出栈,同时S1变为后台任务,S2变为前台任务
d) 退出顺序:B → A → 桌面(按两次返回键)
此时再按返回,B从S2中出栈,S2任务栈不存在了,此时只能切换到后台任务栈S1,显示A,
再次按返回键,A从从S1中出栈,就回到了桌面
3. A为standard,B、C为singleInstance
此时会有3个任务栈,默认任务栈设为S1,因为singleInstance会创建独立的任务栈,不用设置taskAffinity,设置B在的任务栈为S2, C在的任务栈为S3
<activity android:name=".A" 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=".B" android:launchMode="singleInstance"/> <activity android:name=".C" android:launchMode="singleInstance"/>
启动流程:A → B → C → A → B
退出顺序:B → A → A → C → 桌面(按4次返回键)
a) A → B → C:
启动A:A的taskAffinity继承自包名,创建默认任务栈(即S1),然后将在S1中创建A,S1为前台任务栈
启动B:创建一个新的任务栈(设为S2),在S2中创建B
启动C:创建一个新的任务栈(设为S3),在S2中创建C
b) A → B → C → A:
再启动A,因为C为singleInstance,S3任务栈只会放活动C,并且A是standard,不会创建新的任务栈,所以此时切换到默认任务栈S1,并新建一个A添加到S1。图二中两个A虽然看起来不在一起,但是他们的栈号都为304
c) A → B → C → A → B:
启动B,因为B为singleInstance,此时S2变为前台任务栈
d) 退出顺序:B → A → A → C → 桌面
此时再按返回,B从S2中出栈,S2任务栈不存在了,此时只能切换到后台任务栈S1,显示最上面的A(设为A1,下面的A设为A2),
再次按返回键A1从S1出栈,显示A2
再次按返回键A2从S1出栈,S1任务栈不存在了,S3变为前台任务,显示C
再次按返回键C从S3出栈,退回到桌面
PS
1. 如果例子2中,设置了A第一次启动B,第二启动C,即A → B → C → A → C,此时退出顺序为C → B → A,因为从A启动C 后,C在S2的栈顶,直接将前台任务切换到S2,不会将任何活动出栈
2. startActivityForResult所启动的活动的启动模式不能是singleInstance和singleTask,则onActivityResult()便立刻被回调了,且resultCode值为RESULT_CANCEL。
singleTask的原因如上一点,因为下一个返回的活动可能是其他活动,同时如果启动的活动为singleTask并且在该任务栈的底部,会把调用startActivityForResult的活动清出任务栈
singleInstance,不清楚为啥,可能不同任务栈的原因