关于android activity启动模式

android的activity作为四大组件之一,其启动模式主要负责它的启动方式,只有真正了解了启动模式我们才能在activity的使用上得心应手。

1.Task

这个Task实际上就是一个栈(栈的特点就是先进后出,就像一个瓶子,你先装进去的东西在瓶子最下面你拿出来的时候也就只有先把上面的拿出来完才能拿到下面的东西),这个Task就是你启动的一系列的Activity的集合,当你启动一个Activity的时候,这个Activity就会被压入栈顶,当你通过返回键或者其他方式finnish掉这个activity的时候,这个activity就会被弹出,基本情况如下图显示(默认启动模式下)一个栈(栈的特点就是先进后出,就像一个瓶子,你先装进去的东西在瓶子最下面你拿出来的时候也就只有先把上面的拿出来完才能拿到下面的东西),这个Task就是你启动的一系列的Activity的集合,当你启动一个Activity的时候,这个Activity就会被压入栈顶,当你通过返回键或者其他方式finnish掉这个activity的时候,这个activity就会被弹出,基本情况如下图显示(默认启动模式下)


然而这样并不能满足所有人的需求所有我们设想一个情形:我们要做一个图片浏览器,第一个界面是图片列表界面(假设为PictureListActivity),第二个界面是浏览该张图片(假设为PictureViewActivity)。在PictureViewActivity中可以startActivity来选择启动浏览界面浏览上一张和下一张。如果每一张图片的浏览启动一个PictureViewActivity(当然你可能不是采用这种方式来浏览上一张和下一张,这里只是举个例子),如果采用standard模式的话,就会出现多个PictureViewActivity在堆栈中堆叠的情形。

显然这不适合我们的需求,我们想要的一般是只启动一个PictureViewActivity来展示。Android为了使我们能够打破默认的堆栈的先后出的模式,提供了两个种方式:一种是在AndroidManifest.xml定义Activity时指定它的加载模式,另一种是在用Intent开启一个Activity时,在Intent中加入标志。如果两种方式都用了,则后者的优先级更高。

两种方式的差别在于,前者在于描述自己,向别的Acttivity等声明你们如何来加载我;而后者则是动态的,指出我要求你(要启动的Activity)如何来加载。本文的重点在于研究在AndroidManifest.xml中声明加载模式,下面我们就来了解具体的启动模式及其特性来选择对应的启动模式实现我们想要的功能。

2.launchMode

启动一个Activity有两种方式,一种就是通过Launcher,另外一种是通过程序代码调用startActivity函数实现(验证过AppWidget其实与这种方式是一致的)其实影响Activity启动关键点大致有三个因素:Activity注册信息中的launchMode、启动Activity时Intent中的launchFlags和Activity注册信息中的taskAffinity、allowTaskReparenting、clearTaskOnLaunch、alwaysRetainTaskState、finishOnTaskLaunch等信息。通常情况下,我们只需要针对第一个因素进行合理设置就能满足我们应用开发的需求了。

2.1standard

不管Activity实例是否存在,都会创建一个新的实例装入Task。(每次通过这种模式来启动目标Activity时,android总会为目标Activity创建一个新的实例,并将该Activity添加到目前的Task栈中。这种模式不会启动新的Task,新的Activity将被添加到原有的Task中)。只管往上加,啥都不管,就是任性。

示例:现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,都采用默认的加载模式,栈的情况是怎么样的呢

2.2singleTop

被跳转的Activity位于Task顶部时:不会创建新的实例,直接复用已有的Activity实例

被跳转的Activity不是位于顶部时:创建一个新的实例,同standard模式相似

示例:现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,都采用singleTop模式,栈的情况是怎么样的呢


2.3singleTask

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

b)如果将要启动的目标Activity已经位于Task栈顶,此时同singleTop模式

c)如果将要启动的目标Activity没有位于Task栈顶,系统将会把位于该Activity上面的所有Activity移除Task栈,从而使得目标Activity转入栈顶。

示例:现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,都采用singleTask模式,栈的情况是怎么样的呢


2.4singleInstance

a)如果将要启动的目标Activity不存在,系统会先创建一个全新的Task,在创建目标Activity的实例,并将它加入新的Task的栈顶。

b)如果将要启动的目标Activity已经存在,无论它位于哪个应用程序中,无论它位于哪个Task中,系统会把该Activity所在的Task转到前台,从而使用该Activity显示出来。

需要指出:采用单例模式加载Activity所在Task只包含该Activity

示例:现在我们假设 A 跳到 B ,然后 B 跳到 B,再 B 跳到 A,都采用singleInstance模式,栈的情况是怎么样的呢


3.四种加载模式的区别


3.1所属task的区别

“standard”和”singleTop”的activity的目标task,和收到的Intent的发送者在同一个task内,就相当于谁调用它,它就跟谁在同一个Task中。除非Intent包括参数FLAG_ACTIVITY_NEW_TASK。如果提供了FLAG_ACTIVITY_NEW_TASK参数,会启动到别的task里。 

“singleTask”和”singleInstance” 总是把要启动的activity作为一个task的根元素,他们不会被启动到一个其他task里。

 

3.2是否允许多个实例

“standard”和”singleTop”可以被实例化多次,并且是可以存在于不同的task中;这种实例化时一个task可以包括一个activity的多个实例; 

“singleTask”和”singleInstance”则限制只生成一个实例,并且是task的根元素。 

singleTop 要求如果创建intent的时候栈顶已经有要创建的Activity的实例,则将intent发送给该实例,而不创建新的实例。

 

3.3是否允许其它activity存在于本task内

“singleInstance”独占一个task,其它activity不能存在那个task里;如果它启动了一个新的activity,不管新的activity的launch mode 如何,新的activity都将会到别的task里运行(如同加了FLAG_ACTIVITY_NEW_TASK参数)。 

而另外三种模式,则可以和其它activity共存。

 

3.4是否每次都生成新实例

“standard”对于每一个启动Intent都会生成一个activity的新实例; 

“singleTop”的activity如果在task的栈顶的话,则不生成新的该activity的实例,直接使用栈顶的实例,否则,生成该activity的实例。

比如:

现在task栈元素为A-B-C-D(D在栈顶),这时候给D发一个启动intent

如果D是 “standard”的,则生成D的一个新实例,栈变为A-B-C-D-D。 

如果D是singleTop的话,则不会生产D的新实例,栈状态仍为A-B-C-D 

如果这时候给B发Intent的话,不管B的launchmode是”standard” 还是 “singleTop” ,都会生成B的新实例,栈状态变为A-B-C-D-B。

“singleInstance”是其所在栈的唯一activity,它会每次都被重用。

“singleTask”  如果在栈顶,则接受intent,否则,该intent会被丢弃,但是该task仍会回到前台。 当已经存在的activity实例处理新的intent时候,会调用onNewIntent()方法,如果收到intent生成一个activity实例,那么用户可以通过back键回到上一个状态;如果是已经存在的一个activity来处理这个intent的话,用户不能通过按back键返回到这之前的状态。



参考资料:

Android的七巧板Activity之二 Activity的加载模式

android开发笔记之 Activity四种加载模式

Android四种Activity的加载模式

猜你喜欢

转载自blog.csdn.net/tian2342/article/details/51471275