Android中Activity的四种加载模式

之前看Android深入理解Activity和Fragment这一章的时候,看到过Activity的四种加载模式,当时一方面觉得有点晦涩难懂,一方面觉得可能在以后的开发过程中用不到,所以就没有怎么细看。今天在看师兄做的项目代码时,发现在配置文件中都会指定加载模式android:launchMode属性。问了一下师兄,才知道这和属性和效率是有点关系的,于是又回头看了一下,顺便做下笔记,方便以后不懂的时候再过来看看。
配置Activity的时候可以为其指定加载模式,Activity有四种加载模式:

  • standard:标准模式,这是默认的加载模式

  • singleTop:Task顶单例模式

  • singleTask:Task内单例模式

  • singleInstance:全局单例模式

介绍加载模式之前先介绍Android对Activity的管理:Android采用Task来管理多个Activity,当我们启动一个应用时,Android就会为之创建一个Task,然后启动这个应用的入口Activity

Task是一个有点复杂的概念,并不是真实存在的类或者接口,我们无法真正去访问它,但是可以调用Activity的getTaskId()方法来获取它所在的Task的ID。我们可以把Task理解成Activity栈,Task以栈的形式来管理Activity:先启动的Activity被放在Task栈底,后启动的Activity被放在Task栈顶

加载模式就复杂管理实例化,加载Activity的方式,并可以控制Activity与Task之间的加载关系。言归正传,介绍四种加载模式:

standard模式

每次通过这种模式来启动目标Activity时,Android总会为目标Activity创建一个新的实例,并将该Activity添加到当前的Task栈中——这种模式不会启动新的Task,新Activity将被添加到原来的Task中。
看下面的代码片段:

1
2
Intent intent = new Intent(StandardTest.this, StandardTest.class);
startActivity(intent);

这个代码片段就是通过点击按钮让其再次启动自身这个Activity,程序将会不断启动新的StandardTest实例,(因为不同的Activity实例其hashCode是不同的),但它们所在的TaskID总是相同的,这表明这种加载模式不会使用全新的Task。
当用户单击手机的返回键的时候,系统会逐一从Activity栈顶删除Activity实例

singlTop模式

这种模式与standar模式基本相似,不同点是:当将要被启动的Activity已经位于Task栈顶时,系统就不会重新创建目标Activity的实例,而是直接复用已有的Activity实例

如果将上面实例中的StandardTest Activity的加载模式改成standard加载模式,无论用户点击多少次按钮,界面上的程序将不会有任何变化,如果将要被启动的目标Activity没有位于Task栈顶,此时系统会重新创建目标Activity的实例,并将它加载到Task的栈顶

singleTask模式

采用这种加载模式的Activity在同一个Task内只有一个实例,当系统采用singleTask模式启动目标Activity是,可分为以下三种情况

  1. 将要启动的Activity不存在,系统将会创建目标Activity的实例,并将它加入Task栈顶。

  2. 如果将要启动的Activity已经位于Task栈顶,此时与singleTop模式的行为相同。

  3. 如果将要启动的Activity已经存在,但没有位于Task栈顶,系统将会把位于该Activity上面的所有Activity移出Task栈,从而使目标Activity转入栈顶

singleInstance模式

在这种加载模式下,系统保证无论从哪个Task中启动目标Activity,只会创建一个目标Activity实例,并会使用一个全新的Task栈来装载该Activity实例。
当系统采用该模式启动Activity时,可分为以下两种情况:

  • 如果将要启动的目标Activity不存在,系统会先创建一个全新的Task,再创建一个目标Activity的实例,并将它加载到新的Task的栈顶。
  • 如果目标Activity已经存在,无论它在哪个应用程序中,无论它位于哪个Task中,系统将会把该Activity所在的Task转到前台,从而使该Activity显示出来

需要指出的是,采用singleInstance模式加载Activity总是位于Task栈顶,采用singleInstance模式加载Activity所在的Task只包含该Activity。