Activity的启动模式全解standard,singleTop,singleTask,singleInstance

在android中控制Activity的启动模式的属性主要控制两大功能:

1,控制activity 进入哪一个任务task 中,   有两种可能,进入启动task中,进入指定taskAffinity的task中,如果指定taskAffinity的task还不存在,则创建一个

2,控制activity 多次启动的处理模式,       有三种可能,每次都创建新的,如果在顶部不创建新的,  如果存在则清除之上所有的activity

 

activity的taskAffinity属性值默认为application的taskAffinity属性值,application的taskAffinity属性值默认为包名

手动设置taskAffinity属性值时,可以设置任意字符串但是必须包含至少一个’.’点符号,否则apk会在安装时解析包错误

Activity的启动模式中多次启动的处理模式要先确定activity进入的task

activity 的launchMode 静态设置时有四种模式,动态设置(intent flag)时常用的有三种 ,其中让taskAffinity属性起作用的有两种模式 singleTaskFLAG_ACTIVITY_NEW_TASK ,其他launchMode启动模式taskAffinity属性无效

  • launchMode      standard      进入启动task,每次都创建新的实例进入task顶部
    singleTop    进入启动task,如果已有实例并且在task顶部不创建新实例,调用原实例的onNewIntent(),其它情况都创建新的实例进入task顶部
    •                singleTask   进入指定taskAffinity的task,如果指定的task存在,将task移到前台,如果指定task不存在,创建指定taskAffinity的task
    •                                    如果task中存在实例,则移除实例之上的所有实例并显示出来,执行原实例的onNewIntent(),其它情况则创建实例进入task顶部
    •               singleInstance   进入新的task,并且此task内只存在此一个activity ,不再加入别的activity
    •                                          如果task中存在实例,执行实例的onNewIntent()
  • taskAffinity起作用时:       进入指定taskAffinity的task,如果指定的task存在,将task移到前台,如果指定task不存在,创建指定taskAffinity的task

 

 

 

而在Intent当中,flag属性控制activity的启动模式:

FLAG_ACTIVITY_NEW_TASK    进入指定taskAffinity的task,如果指定的task存在,将task移到前台,如果指定task不存在,创建指定taskAffinity的task

每次都创建新的实例进入task顶部

     FLAG_ACTIVITY_SINGLE_TOP   进入启动task

                                                         如果已有实例并且在task顶部不创建新实例,执行实例的onNewIntent(),其它情况都创建新的实例进入task顶部

 

     FLAG_ACTIVITY_CLEAR_TOP    进入启动task

                                                         如果task中存在实例,则移除实例之上的所有实例,如果启动的activity启动模式不是standard模式,或者flag有FLAG_ACTIVITY_SINGLE_TOP属性

                                                         那么调用Activity B的onNewIntent()方法否则销毁原有实例创建新实例进入task顶部,其它情况则创建实例进入task顶部

 

 

 

 

对activity的启动模式属性中Intent的flag属性覆盖<activity>元素中属性设置;

 

在<activity>元素中,有以下几个属性是可以使用的:

  • taskAffinity
  • launchMode
  • allowTaskReparenting
  • clearTaskOnLaunch
  • alwaysRetainTaskState
  • finishOnTaskLaunch

 

而在Intent当中,有以下几个flag是比较常用的:

  • FLAG_ACTIVITY_NEW_TASK
  • FLAG_ACTIVITY_CLEAR_TOP
  • FLAG_ACTIVITY_SINGLE_TOP

 

 

处理affinity

affinity可以用于指定一个Activity更加愿意依附于哪一个任务,在默认情况下,同一个应用程序中的所有Activity都具有相同的affinity,所以,这些Activity都更加倾向于运行在相同的任务当中。当然了,你也可以去改变每个Activity的affinity值,通过<activity>元素的taskAffinity属性就可以实现了。

 

taskAffinity属性接收一个字符串参数,你可以指定成任意的值(经我测试字符串中至少要包含一个.),但必须不能和应用程序的包名相同,因为系统会使用包名来作为默认的affinity值。

 

affinity主要有以下两种应用场景:

  • 当调用startActivity()方法来启动一个Activity时,默认是将它放入到当前的任务当中。但是,如果在Intent中加入了一个FLAG_ACTIVITY_NEW_TASK flag的话(或者该Activity在manifest文件中声明的启动模式是”singleTask”),系统就会尝试为这个Activity单独创建一个任务。但是规则并不是只有这么简单,系统会去检测要启动的这个Activity的affinity和当前任务的affinity是否相同,如果相同的话就会把它放入到现有任务当中,如果不同则会去创建一个新的任务。而同一个程序中所有Activity的affinity默认都是相同的,这也是前面为什么说,同一个应用程序中即使声明成”singleTask”,也不会为这个Activity再去创建一个新的任务了。
  • 当把Activity的allowTaskReparenting属性设置成true时,Activity就拥有了一个转移所在任务的能力。具体点来说,就是一个Activity现在是处于某个任务当中的,但是它与另外一个任务具有相同的affinity值,那么当另外这个任务切换到前台的时候,该Activity就可以转移到现在的这个任务当中。
    那还是举一个形象点的例子吧,比如有一个天气预报程序,它有一个Activity是专门用于显示天气信息的,这个Activity和该天气预报程序的所有其它Activity具体相同的affinity值,并且还将allowTaskReparenting属性设置成true了。这个时候,你自己的应用程序通过Intent去启动了这个用于显示天气信息的Activity,那么此时这个Activity应该是和你的应用程序是在同一个任务当中的。但是当把天气预报程序切换到前台的时候,这个Activity又会被转移到天气预报程序的任务当中,并显示出来,因为它们拥有相同的affinity值,并且将allowTaskReparenting属性设置成了true。

清空返回栈

 

如何用户将任务切换到后台之后过了很长一段时间,系统会将这个任务中除了*底层的那个Activity之外的其它所有Activity全部清除掉。当用户重新回到这个任务的时候,*底层的那个Activity将得到恢复。这个是系统默认的行为,因为既然过了这么长的一段时间,用户很有可能早就忘记了当时正在做什么,那么重新回到这个任务的时候,基本上应该是要去做点新的事情了。

 

当然,既然说是默认的行为,那就说明我们肯定是有办法来改变的,在<activity>元素中设置以下几种属性就可以改变系统这一默认行为:

 

alwaysRetainTaskState

如果将*底层的那个Activity的这个属性设置为true,那么上面所描述的默认行为就将不会发生,任务中所有的Activity即使过了很长一段时间之后仍然会被继续保留。

 

clearTaskOnLaunch

如果将*底层的那个Activity的这个属性设置为true,那么只要用户离开了当前任务,再次返回的时候就会将*底层Activity之上的所有其它Activity全部清除掉。简单来讲,就是一种和alwaysRetainTaskState完全相反的工作模式,它保证每次返回任务的时候都会是一种初始化状态,即使用户仅仅离开了很短的一段时间。

 

finishOnTaskLaunch

这个属性和clearTaskOnLaunch是比较类似的,不过它不是作用于整个任务上的,而是作用于单个Activity上。如果某个Activity将这个属性设置成true,那么用户一旦离开了当前任务,再次返回时这个Activity就会被清除掉。