Android中有Activity、Service、BroadcastReceiver和ContentProvider四大组件,Activity是用得最多的且最重要的。
Activity有四种启动模式
Standard模式:标准模式,也就是默认模式,每次start一个Activity都会创建一个新的Activity对象。
SingleTop模式:每次start一个Activity时,如果当前任务栈栈顶恰好是打算要start的Activity对象,那么重用它,否则创建一个新的Activity对象。
SingleTask模式:每次start一个Activity时,如果当前任务栈恰好有打算要start的Activity对象,那么销毁掉它上面的所有其它的Activity对象然后使用这个Activity对象,否则创建一个新的Activity对象。
SingleInstance模式:每次start一个Activity时,如果存在一个栈有且只有一个我们打算要start的那个Activity对象,那么重用它,否则创建一个任务栈,再创建一个新的Activity对象,然后将这个Activity对象压进刚才创建的任务栈中。
从上面可以看出,一直有一个任务栈的东西存在,任务栈是一个很重要的东西,要理解Activity,首先就要彻底理解任务栈。
说的简单点:可以这样想,在Android系统中,存在几个栈,这些栈里面存放的都是Activity对象。
说的深入点:上面说的一个任务栈其实就是一个TaskRecord对象,里面有个Activity列表放Activity对象。
注意这些任务栈是有名字的,每一个栈都有一个affinity(字符串),这个affinity的值为第一个放入该栈中的第一个Activity的taskAffinity属性值。
application节点和activity节点都有taskAffinity这个属性,对于Activity,它就是指定当创建一个组件的对象时该放到哪个任务栈中。默认情况下applicaition节点的taskAffinity属性值为包名,而activity节点的taskAffinity属性值与application节点的taskAffinity属性值一样。
我们可以使用adb shell dumpsys activity > 1.txt 命令得到设备当前任务栈的详细信息并将结果输出到1.txt文件中:
当前系统有两个任务栈,圈出来的就是它们的affinity值,可以看到它们就是第一个放入该任务栈的Activity的taskAffinity值。图中还有许多有用的信息,比如每个任务栈的id,正在运行的Activity,处于前台的任务栈等。
现在我们来考虑这个问题:现在我们要启动一个Activity,它的taskAffinity值指定为已存在的任务栈的affinity值,比如在小米手机上Launcher它自己创建了一个任务栈affinity值为com.miui.home,如果现在我就指定我们一个要启动的Activity的taskAffinity值为com.miui.home,那么这个Activity会被放在为Launcher创建的那个任务栈里吗?
答案是不一定!
1.假如要启动的Activity的运行模式被指定为SingleTask,或者启动是Intent的Flags设置为
FLAG_ACTIVITY_NEW_TASK,那么如果存在相同affinity值的任务栈时使用该任务栈,否则创建新的任务栈。
2.假如要启动的Activity运行模式为Standard或者SingleTop,那么新创建的Activity一定是放到当前任务栈中。
3.如果要启动的Activity运行模式为SingleInstance,那么如果存在一个任务栈恰好只有该要启动的Activity对象,那么重用它否则创建新的任务栈(注意此时系统就有两个任务栈,它们的affinity都是com.miui,home)。
我们再来思考另外一个问题:Activity有个方法叫onNewIntent(Intent intent),什么时候它会被调用呢?
答案很简单:如果重用一个Activity,那么它的onNewIntent方法就会被调用,当然那些生命周期方法是不会被执行(因为没有创建新Activity对象)。
最后在配置清单activity节点还有几个属性
1.clearTaskOnLaunch:
某一个Activity指定了clearTaskOnLaunch为true(默认为false),然后启动这个Activity时创建了一个新的任务栈,那么我们就可以认为该任务栈具有clearTaskOnLaunch属性为true,然后我们有通过这样或者那样的方式在这个任务栈中添加了几个Activity对象,最后把这个任务栈放到后台(就是该任务栈的所有Activity都在后台时)。这时我们再次让该任务栈的某一个Activity移到前台,即这个任务栈又移到前台,那么该任务栈中除了第一个Activity的其它所有Activity都会被销毁,这时会显示第一个Activity。
注意:上面说到的将任务栈的某一个Activity移到前台,这里可以是点击Launcher界面上的图标或者其它的,但是不能是点击任务列表进入。
对于上面描述的流程,举个例子如下:
有一个App,点击Launcher上的图标后启动MainActivity(设置clearTaskOnLaunch为true且启动时创建新的任务栈),然后在MainActivity里面又启动的SecondActivity(创建的Activity对象放在启动MainActivity时创建的任务栈里),现在显示SecondActivity,然后按Home键最小化,这时MainActivity所在的任务栈就移到了后台。假如我们点击Launcher上的图标(那么此时MainActivity所在的任务栈又被移到前台),但这时显示的是MainActivity而不是SecondActivity,因为SecondActivity被销毁了。MainActivity是第一个放到该任务栈中因此不会被销毁。
2.finishOnTaskLaunch:
与clearTaskOnLaunch一样,不过销毁掉的只是那些把finishOnTaskLaunch设置为true的Activity,注意第一个放入任务栈的Activity是不会被销毁掉的,也就是说这个属性对任务栈的根Activity是没用的。
3.alwaysRetainTaskState:
只对根Activity有效,默认值为false,表示当该任务栈处于后台太久时系统可以清除掉出来根Activity以外的所有Activity,设置为true则禁止这行为。
4.allowTaskReparenting:
允许处于后台任务栈的Activity转移到前台任务栈中(affinity相同)
转载请注明原文地址:http://blog.csdn.net/u012619640/article/details/48398621