Android中的任务栈和Activity的启动模式

2022-09-12  本文已影响0人  ModestStorm

1.Android中的任务栈

在Android系统中,任务栈是一种用来存放Activity实例的容器。通常当一个Android应用程序启动时,如果当前环境中不存在该应用程序的任务栈,那么系统就会创建一个任务栈。此后,这个应用程序所启动的Activity都将在这个任务栈中被管理。需要特别注意的是,一个任务栈中的Activity可以来自不同的App,同一个App的Activity也可能不在一个任务栈中。

任务栈的最大特点是先进后出。根据Activity当前栈结构中的位置,来决定该Activity的状态。正常情况下,Android任务栈的工作情况如下图所示:


activitytask.png

Activity1处于栈顶位置,当在Activity1中开启Activity2时,Activity2的实例会被压入栈顶的位置。

task1.png task2.png

同样,在Activity2中开启Activity3时,Activity3的实例也会被压入栈顶的位置。以此类推,无论开启多少个Activity,最后开启的Activity的实例都会被压入栈的顶端,而之前开启的Activity虽然“功成身退”,却仍然保存在栈中,但活动已经停止。系统会保存Activity被停止时的状态。


pop.png

当用户点击返回按钮或者调用finish()方法时,Activity3会被弹出栈,Activity2处于栈顶位置并恢复Activity2被保存的界面状态。

当然任务栈的这种工作特性并不完美,因此可以给Activity设置一些“特权”,来打破这种“和谐”的模式。这种“特权”也就是下面我们将探讨的Activity的启动模式。

2.Activity的启动模式

Activity启动模式有4种,分别是standard、singleTop、singleTask和singleInstance模式。

2.1 standard模式(标准模式)

standard模式是Activity的默认启动方式,每启动一个Activity就会在栈顶创建一个新的实例。因此,这种启动模式下会存在大量相同的实例。当然,这种模式下也允许存在相同的实例。

在实际开发中,闹钟程序通常使用这种模式。

例如:创建一个启动模式为standard的ActivityA,点击A跳转到A页面,点击两次 A->A->A,这样栈内就会出现三个相同的A实例,这时候点击返回键的时候你就会发现,我们需要点击三次返回键才能退出页面。

clock.png

2.2 singleTop模式(栈顶复用模式)

在某些情况下,会发现使用standard模式启动的Activity并不合理。例如,当Activity已经位于栈顶,再次启动该Activity还需要创建一个新的实例压入任务栈,而不能直接复用之前的Activity实例。

在这种情况下,使用singleTop模式启动Activity更合理,该模式会判断要启动的Activity实例是否位于栈顶,如果位于栈顶,则直接复用,否则创建新的实例。实际开发中,浏览器的书签采用这种模式。

如qq接收到消息后弹出Activity界面,如果一次来10条消息,总不能一次弹10个Activity。

例如:创建两个Activity A和B,将B的启动模式设置成SingleTop。点击A跳转到B,点击B跳转到B , A->B->B 这时候点击返回按钮的时候,只需要点击一次就返回到A页面了。

singletop1.png singletop2.png

2.3 singleTask模式(栈内复用模式)

使用singleTop模式虽然可以很好地解决栈顶重复压入Activity实例的问题。但如果要启动的Activity的未处于栈顶,则还会在栈中压入多个不相连的Activity实例。需要Activity在栈中有且只有一个实例,借助singleTask模式可以实现。

当Activity的启动模式指定为singleTask时,每次启动该Activity时,系统会首先检查栈中是否存在当前的Activity实例,如果存在,直接使用该Activity,并将当前Activity的实例上面的所有实例全部弹出栈。实际开发中,浏览器主界面通常采用这种模式。

例如:创建两个Activity A和B,将A的启动模式设置成SingleTask。点击A跳转到B,点击B跳转到A , A->B->A 这时候点击返回按钮的时候,点击一次就退出页面了。

singleTask.png

taskAffity属性

taskAffinity属性用于给Activity单独指定任务栈名称。这个名称不能和包名相同,否则就没有意义。注意taskAffinity属性值为String,而且中间必须包含有分隔符 . (英文状态下的点),比如com.baidu.test.

另外,如果想要指定一个非包名的任务栈,该Activity一定要把启动模式设置为singleTask模式,否则不会生效。如果taskAffinity指定的名称是其他程序的包名,那么可以不结合singleTask。注意:任务栈分为前台任务栈和后台任务栈,后台任务栈里面的Activity全部处于onStop状态。

设定taskAffinity之后,当启动这个Activity之后,如果之前没有任务栈的存在,那么就启动系统会开辟出来一个新的任务栈用于存放这个activity,如果已经存在了这个任务栈,那么这个activity任务栈就会被转移到前台。

在Receiver和Service中启动一个Activity时,因为在Receiver/Service中并不存在Activity栈。严格意义上说,FLAG_ACTIVITY_NEW_TASK会判断你要启动的Activity的栈是否已经存在,如果存在,就会带到前台,并不会创建新的栈。如果不存在,才会创建新栈。

2.4 singleInstance模式

singleInstance模式是4种启动模式中最特殊的一种,指定singleInstance模式的Activity会启动一个新的任务栈来管理该Activity实例,无论从哪个任务栈中启动该Activity,该Activity实例在整个系统中都只有一个。Android的桌面使用的就是该模式。

在singleInstance模式下,该Activity在整个android系统内存中有且只有一个实例,而且该实例单独尊享一个Task。换句话说,A应用需要启动的MainActivity 是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A单独在这个新的任务栈中,如果此时B应用也要激活MainActivity,由于栈内复用的特性,则不会重新创建,而是两个应用共享一个Activity的实例

启动singleInstance模式的Activity有两种情况:

情况一:要启动的Activity实例在栈中不存在,系统先创建一个新的任务栈,然后压入Activity。

情况二:要启动的Activity实例已存在,系统把该Activity所在的任务栈转移到前台,从而使Activity展示。

实际开发中,来电界面通常使用该模式。

例如创建三个Activity A、B、C,将B的启动模式设置成singleInstance,点击A跳转到B,点击B跳转到C,这时候点击返回按钮,你会发现会从C直接返回到A而不是B。因为B和A、C不是一个任务栈,B是单独、独立的一个任务栈。

singleInstance.png

如果A应用启动了B应用的页面,任务栈情况是怎么样的呢?会不会是同一个任务栈呢?

结论:
1.当被启动应用的activity是standard、singleTop时,被启动的activity是直接被压入调用者(这里的应用a)的任务栈顶。二者是同一个任务栈。

2.当被启动应用的activity是singleTask、singleInstance时,被启动的activity是使用单独的任务栈。
另外,不论哪种模式,跨应用启动的activity都是运行在其所属应用的进程中.

上一篇下一篇

猜你喜欢

热点阅读