Activity 的LaunchMode
为什么有启动模式:安卓系统在默认情况下,当我们多次启动同一个Activity的时候,系统就会创建多个实例并把他们一一放到任务栈中,当我们点击back键时,会发现这些Activity会一一退回。这种多次创建同一个实例的行为是很傻叉的,开发安卓系统的人自然不会想不到这一点,于是就有了各种启动模式来修改系统的默认行为山山水水!
任务栈可以简单理解为Activity运行提供的场所,是一种栈结构.
四种模式:standard、singleTop、singleTask、singleInstance
Standard:标准模式
- 每次启动Activity都会都会创建一个实例.
- 谁启动这种模式的Acitivity,该活动就在谁的任务栈中.
- 经典的创建模式.
此中模式 用ApplicationContext去启动活动时并没有所谓的任务栈,是必出错,解决的方法是既然没有任务栈就创建一个任务栈给它,即指定启动的Activity的FLAG_ACTIVITY_NEW_TASK标志位,则这样启动的时候就会创建一个任务栈,而这个时候是以singleTask模式启动的.
singleTop:栈顶复用模式
- 如果新的Activity在栈顶,那么此Activity不会被重新创建,同时他的onNewIntent方法会调用,通过此方法的参数我们可以取出当前请求的信息.
- 这个Activity的onCreate onStart不会被调用,因为它没有发生改变.
- 如果Activity的实例已经存在,但是不在栈顶,新的Activity仍会重建.
小栗子:
目前栈内为ABCD A 栈底 D站顶
此时如果再次启动D,如果D的启动模式是singleTop ,则栈内情况依然是ABCD
如果D的启动模式standard,那么D会被重新创建,栈内情况变为ABCDD.singleTask:栈内复用模式
- 只要Activity在站内存在,就不会重新创建实例.
- 系统也会调用其onNewIntent.
具体过程是:当这样一个模式Activity A启动后,系统会首先寻找是否存在A想要的任务栈,如果不存在就重新创建一个任务栈,然后创建A的实例把A放入栈中.如果存在A所需要的任务栈
并存在A的实例,那么系统会把A弄到栈顶,并调用他的onNewIntent方法,如果实例不存在,创建A的实例并把它压入栈中.
这一点需要特别注意 ,活动D所需的任务栈是S1,并且S1的当前的情况为 ADBC,根据核内服用原则,D不会被重新创建,系统会把D切换到栈顶,并调用其onNewInstant方法,由于singleTask具有clearTop的效果,会导致D上面的Activity全部出栈,于是S1就成了AD.
singleInstance:单实例模式 加强版的singleTask,除了具备singleTask的所有特性外,此模式的Activity单独处于一个任务栈中,可想而知由于栈内复用的特性,后续请求君不会创建新的Activity;
这里四种启动模式就讲完了;举个栗子: 假设目前有两个任务栈,前台任务栈(A、B activity)和后台任务栈(C、D activity
),CD启动模式为SingleTask. 现在启动D
则整个后台任务栈都会切换到前台,注意是任务栈到前台,这个时候整个后退列表是变成ABCD;当用户按back键时activity会一一出栈;如下图所示![]()
这里需要明确一点 ABCD只是一个回退列表 可不是同一个任务栈!如果是启动C 然后再回退又不一样了,C会把D先挤出栈,因为D处于后台任务栈栈顶;
何为任务栈? 说到那武大,有个貌美如花的媳妇儿,不能跑题,首先要说一下一个重要参数:TaskAffinity 翻译为任务相关性,干啥的呢,标识了一个Activity所需要的任务栈的名字。
默认情况下,所有Activity所需要的任务栈的名字为应用的包名。于是我们当然可以为不走寻常路的Activity单独指定TaskAffinity属性,如果指定的名称和包名相同,相当于没指定。
任务栈可分为前台任务栈和后台任务栈,后台任务栈中的Activity中Acitivity处于暂停状态,可以通过切换将后台任务栈再次调到前台.
里面有蛮多暗黑的东西存在,当TaskAffinity和singleTask启动模式匹配使用的时候,他是具有该模式的Activity的目前任务栈的名字,待启动的Activity会运行在名字和TaskAffinity相同的任务栈中.
当TaskAffinity和allowTaskReparenting结合使用的时候,分析会有些复杂:
当一个应用A启动了应用B的某个Activity后,如果这个Activity的allowTaskReparenting为true的话,那么当应用B启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈。
那如何设置Activity的启动模式呢
- 通过AndroidMenifest
- 使用intent
IntentFilter的匹配规则
这里主要说的是隐式调用,隐式调用需要Intent能够匹配目标组件的IntentFilter设置的过滤信息,如果不匹配将无法启动目标Activity.IntentFilter过滤信息有action,category,data,下面是具体的过滤规则:
同一个Intent同时配置所有的约束类别才算完全匹配;而一个intent只要匹配其中的一组IntentFilter即可
- Action的匹配规则
- Category的匹配规则
- Data的匹配规则
这个坑挖的很深,以后再补上吧 这一部分不会经常用到