Android中的任务栈和Activity的启动模式
一、Android中的任务栈
在Android系统中,任务栈是一种用来存放Activity实例的容器。通常当一个Android应用程序启动时,如果当前环境中不存在该应用程序的任务栈,那么系统就会创建一个任务栈。此后,这个应用程序所启动的Activity都将在这个任务栈中被管理。需要特别注意的是,一个任务栈中的Activity可以来自不同的App,同一个App的Activity也可能不在一个任务栈中。
任务栈的较大特点是先进后出。根据Activity当前栈结构中的位置,来决定该Activity的状态。正常情况下,Android任务栈的工作情况如下图所示:
Activity1处于栈顶位置,当在Activity1中开启Activity2时,Activity2的实例会被压入栈顶的位置。
同样,在Activity2中开启Activity3时,Activity3的实例也会被压入栈顶的位置。以此类推,无论开启多少个Activity,最后开启的Activity的实例都会被压入栈的顶端,而之前开启的Activity虽然“功成身退”,却仍然保存在栈中,但活动已经停止。系统会保存Activity被停止时的状态。
当用户点击返回按钮或者调用finish()方法时,Activity3会被弹出栈,Activity2处于栈顶位置并恢复Activity2被保存的界面状态。
当然任务栈的这种工作特性并不完美,因此可以给Activity设置一些“特权”,来打破这种“和谐”的模式。这种“特权”也就是下面我们将探讨的Activity的启动模式。
二、Activity的启动模式
Activity启动模式有4种,分别是standard、singleTop、singleTask和singleInstance模式。
1.standard模式(标准模式)
standard模式是Activity的默认启动方式,每启动一个Activity就会在栈顶创建一个新的实例。因此,这种启动模式下会存在大量相同的实例。当然,这种模式下也允许存在相同的实例。
在实际开发中,闹钟程序通常使用这种模式。
例如:创建一个启动模式为standard的ActivityA,点击A跳转到A页面,点击两次 A->A->A,这样栈内就会出现三个相同的A实例,这时候点击返回键的时候你就会发现,我们需要点击三次返回键才能退出页面。
2.singleTop模式(栈顶复用模式)
在某些情况下,会发现使用standard模式启动的Activity并不合理。例如,当Activity已经位于栈顶,再次启动该Activity还需要创建一个新的实例压入任务栈,而不能直接复用之前的Activity实例。
在这种情况下,使用singleTop模式启动Activity更合理,该模式会判断要启动的Activity实例是否位于栈顶,如果位于栈顶,则直接复用,否则创建新的实例。实际开发中,浏览器的书签采用这种模式。
例如:创建两个Activity A和B,将B的启动模式设置成SingleTop。点击A跳转到B,点击B跳转到B?, A->B->B?这时候点击返回按钮的时候,只需要点击一次就返回到A页面了。
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?这时候点击返回按钮的时候,点击一次就退出页面了。
4.singleInstance模式
singleInstance模式是4种启动模式中最特殊的一种,指定singleInstance模式的Activity会启动一个新的任务栈来管理该Activity实例,无论从哪个任务栈中启动该Activity,该Activity实例在整个系统中都只有一个。Android的桌面使用的就是该模式。
启动singleInstance模式的Activity有两种情况:
情况一:要启动的Activity实例在栈中不存在,系统先创建一个新的任务栈,然后压入Activity。
情况二:要启动的Activity实例已存在,系统把该Activity所在的任务栈转移到前台,从而使Activity展示。
实际开发中,来电界面通常使用该模式。
例如创建三个Activity A、B、C,将B的启动模式设置成singleInstance,点击A跳转到B,点击B跳转到C,这时候点击返回按钮,你会发现会从C直接返回到A而不是B。因为B和A、C不是一个任务栈,B是单独、独立的一个任务栈。