定义启动模式
启动模式允许你定义一个新的Activity实例如何与当前的任务联系,你可以用一下两种方式定义不同的模式:
用Manifest文件:
在Manifest中声明一个Activity时,你可以指定此Activity启动时如何关联任务的。
使用Intent标记:
当我们调用startActivity()时,你可以增加一个标记来描述新的Activity与当前任务的关系。
因此如果Activity A启动Activity B,B可以在Manifest中定义当前任务的关系A也可以请求B与当前任务的关系,如果两者都定义了,那么A的请求时的指定要比B在Manifest中指定的优先级要高。
注意:有些启动模式指出Manifest配置但是不支持Intent启动标记,有些支持Intent启动标记但不支持Manifest配置。
使用Manifest文件
当你在Manifest文件中声明一个Activity时,你可以通过<activity>标签的launchMode属性指定它与当前任务的关系。有四种模式可以指定:
“standard”
默认的。
“singleTop”
如果一个Activity的实例已经存在于当前任务的最顶层,系统会同过调用onNewIntent()方法调用哪个方法,而不是创建一个新的实例。这个Activity可以被实例化多次,但是每个实例属于不同的任务,一个任务可以cunzai多个实例(但是仅当返回堆栈顶层的Activity不是Activity的实例)
假设,一个任务的返回堆栈包括主Activity A以及B,C,D在最顶层(A-B-C-D),有一个请求D的Intent ,如果D定义的时“standard”模式,一个新的实例就会被启动,堆栈变成A-B-C-D-D。然而如果D定义的时“singleTop”模式,已经存在的D的实例接收到这个Intent,就会鸟用onNewIntent(),因为它是在堆栈的最顶层,因此堆栈还是A-B-C-D。然而,如果有个请求B的Intent,即使模式是“singleTop”,也是要创建一个新的实例添加的堆栈中。
注意:当一个Activity的实例被创建,用户可以通过返回按钮回来原来的Activity,但是当一个已经存在的实例接受了Intent,在新的Intent到达之前,用户是无法通过返回键回到Activity的状态。
“singleTask”
系统创建一个新的任务并且实例化任务中根Activity,然而如果这个Activity存在别的任务中,系统将会通过调用它的onNewIntent()方法指派这个Intent到这个存在的实例上,而不是创建一个新的实例,一次只能存在一个Activity实例。
注意:尽管Activity在一个新的任务中启动,返回按钮仍然能够回到上一个Activity。
“singleInstance”
和“singleTask”一样,除了系统不会启动持有这个实例的任务的其他的Activity,这个Activity总是单独的,仅仅是任务的成员。任何一个以这种方式启动的将会在一个新的任务中打开。
又如,Android的浏览器应用每次都在同一个任务中打开,因此配置为singleTask,这就是说如果你的应用要打开浏览器,这个Activity和你的应用并不在同一个任务中,或者是为浏览器重启创建一个新的任务,或者如果浏览器已经有一个任务,直接把它调到前台。
不管一个Activity是创建一个新的任务还是在同一个任务中,返回按钮总是能回到上一个Activity,但是如果启动一个配置为singleTask的Activity,如果这个Activity的实例存在于后台进程中,整个后台进程将会被调到前台,如图四证明了这种方案。
图四
想了解更多关于Manifest中配置启动模式的知识,参考<activity>元素的文档
注意:尽管你为Activity指定的行为都可以通过启动Intent时设置标记来重载的。
使用Intent标志
在启动一个Activity时,我们可以通过指定标志来修改Activity和任务的关系,有如下四种标志:
FLAG_ACTIVITY_NEW_TASK
在新的任务中启动Activity,如果Activity所在的任务已经在运行,这个任务将会到前台,展示它停止时的状态,这个Activity通过onNewIntent()收到Intent。这个和前面讲的"singleTask"具有相同的效果。
FLAG_ACTIVITY_SINGLE_TOP
如果被启动的Activity正是当前的Activity,这个已经存在的实例就会调用onNewIntent(),而不是创建一个新的实例。
FLAG_ACTIVITY_CLEAR_TOP
如果被启动的Activity在正在运行的任务中,堆栈中在它之上的Activity将会全部清除,这个Intent将会通过onNewIntent()重启这个实例。配置启动模式里面没有此功能。
FLAG_ACTIVITY_CLEAR_TOP经常和FLAG_ACTIVITY_NEW_TASK结合着使用,当他俩结合使用时,就能在另一个任务中启动已经存在的Activity。
处理共用性
共用性象征着Activity属于哪个任务。默认的一个应用中的所有Activity各自都有一个共用性,因此,所有的Activity默认的属于同一个任务。但是我们可以修改一个Activity的共用性。不同应用中的Activity也可以公用一个共用性,或者同一个应用中的Activity也可以被分派给不同的共用性。
你可以通过<activity>的元素takeAffinity来修改Activity的共用性。这个takeAffinity属性的值是一个字符串,并且不能与默认的包名一样,因为系统用这个名字作为应用默认的任务共用性。
清除任务堆栈
如果用户离开一个任务时间过长,系统会清除任务中除了根Activity为外的所有Activity,当用户再次回到这个任务时,只有根Activity被存储,因为在一般这种情况下用户就像丢弃之前做的事情,再次回来时时希望开始新的事情。
我们可以通过修改<activity>的属性来修改这种行为:
alwaysRetainTaskState
如果一个任务的根Activity将此属性设置为true,刚才说的默认行为就不会出现,这任务会保存所有Activity的状态即使时间很长。
clearTaskOnLaunch
如果一个任务的根Activity将此属性设置为true,堆栈将会清除所有的Activity回到根Activity,换句话说,就是与alwaysRetainTaskState相反,用户将会回到任务的初始状态,即使刚刚离开。
finishOnTaskLaunch
这个属性根clearTaskOnLaunch比较像,但是它是针对一个Activity,而不是一个任务堆栈,它可以让任何一个Activity消失,包括主Activity。如果它设为true,这个Activity只是当前属于此任务,如果用户离开回到任务中,这个Activity将不会存在。
启动一个任务
你可以通过给一个Activity设置Intent filter为"android.intent.action.MAIN"以及指定action为"android.intent.action.LAUNCHER",来将此Activity作为一个任务的起点。
用户必须能够离开一个任务,并且能够通过主Activity返回到此任务,因此“singleTask”和“singleInstance”经常被用在主Activity中,设想一个这个filter丢失之后将会发生什么:一个Intent启动一个“singleTask”Activity,初始化一个新的任务,用户在此任务中操作了之后,点击桌面按钮,这个任务进入到后台,现在用户就不能再次回到这个任务中,因为他不是应用的启动Activity。
如果你不行让用户再次回到此Activity,就将<activity>中finishOnTaskLaunch设置为true