【基础】任务栈与启动模式

对于Android的启动模式,似乎是最简单的入门知识了,StandardSingleTopSingleTaskSingleInstance
本文重点对singleTask进行加深理解。

入门及使用

任务栈(Task)

要了解启动模式的具体表现流程,首先要了解任务栈。官网介绍说任务与回退栈,这里直接成为任务栈。

一个Application一般是由多个Activity构成,而多个Activity的管理,Android已经帮我们管理好了,使用栈方式管理,也就是先进后出,启动模式可以理解为四种不同的进栈出栈方式。而这个管理activity的栈成为任务栈。

  1. 一个app默认只有一个任务栈,由系统指定。
  2. 一个app可以存在多个任务栈,需要自己手动设置。多个任务栈时,当前activity所在栈处于前台,其余栈处于后台。

启动模式

1. standard

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<activity android:name=".A"
      android:launchMode="standard"/>

standard是android中默认的启动模式,如果你新建一个应用,不进行任何修改,那么MainActivity的启动模式就是standard

standard会进行重复创建实例,比如应用中有Main和A两个activity,那么Main -> A -> A -> Main这样的启动顺序,就会如下图所示:

standard重复创建实例

点击back返回,则会正常出栈,直到最后一个出栈,app关闭回到桌面。

按back键返回示意图

这种模式一般不推荐使用,会占用过多内存,页面重复。

2. singleTop 栈顶复用

<activity android:name=".A"
      android:launchMode="singleTop"/>

只有这个activity处于栈顶位置时,不会重新创建实例,而是会使用已经创建好的实例。并且会调用onNewIntent方法,可以根据此方法获取intent实例。

singleTop示意图

应用情景:
点击通知跳转到文章详情页,如果当前用户正在文章详情页查看时进行点击,那么可以使用singleTop来确保不会重复创建实例,避免用户点击回退键时还是文章详情页。

3. singleTask 栈内只有一个实例

<activity android:name=".Main"
      android:launchMode="singleTask"/>

singleTask模式是栈内只允许存在一个实例,当这个实例已经创建,会直接使用这个实例,而不会重新创建,在这个实例上方的其他activity也将全部出栈销毁。重用实例会调用onNewIntent

比如设置MainsingleTask,打开Main后,再打开A,B,C三个默认standard的Activity,由C打开Main,则栈中只剩下Main

singleTask
注意1:singleTask 和 taskAffinity

每个activity都有taskAffinity属性,如果没有显式的指明taskAffinity,那么就等于Application指明的taskAffinity,而如果Application也没有指明,那么该taskAffinity的值就等于应用的包名。

默认情况下singleTask所在的任务栈就是app启动的默认栈,而当设置了taskAffinity后,那么启动设置singleTask的activity,那么就会新创建一个栈来存放activity。

<activity android:name=".A"
    android:launchMode="singleTask"
    android:taskAffinity=".myNewTask"/>

这样一个app就存在两个任务栈。

启动流程是这样的:
a)判断当前任务栈taskAffinity是否为.myNewTask,如果是的话,直接将该activity置于当前任务栈栈顶
b)如果当前任务栈taskAffinity不为.myNewTask,则检查是否存在一个任务栈taskAffinity值为.myNewTask,如存在,则将该任务栈移到前台,并将该activity置于栈顶
c)如果并不存在一个任务栈taskAffinity值为.myNewTask,那么将会为该activity创建一个新的任务栈,该任务栈显示在前台

注意2:SingleTask && MAIN启动

每个app都会存在一个启动的activity,即点击图标进入的第一个activity

<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

当此时的MainActivity设置android:launchMode="singleTask"时,会产生这样一个现象:回退Home后重新打开app,总是会重新打开,而不记录最后打开的页面。

这个其实就是由于栈内存在一个实例导致,因为之前已经启动过app,也就是后台存在这个app的任务栈,那么回退到Home再重新打开,首先会找到这个App对应的任务栈,而后由于启动的MainActvitySingleTask,在任务栈中已经存在,那么会直接使用这个存在的实例,又因为MainActivity处于栈底,那么启动这个已经存在的实例会将上方所有的activity都清除出栈

注意3:allowTaskReparenting && taskAffinity

activitytaskAffinity,默认指向applicationtaskAffinity,默认是mainfestpackage值,也就是常说的包名。

allowTaskReparenting这个属性很有意思,可以将activity由一个task迁移到另一个task,而将activity迁移到另一个task是又条件的:

  1. 首先指定android:allowTaskReparenting="true"
  2. 指定android:taskAffinity=".xx"这个.xx并不是你应用本身的taskAffinity,或者不同应用默认taskAffinity本身就不同,可以不指定taskAffinity
  3. 发生Task Reset,点击Home再启动APP可发生Task Reset
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.taskb">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".OtherTaskActivity"
            android:allowTaskReparenting="true"
            android:taskAffinity=".othertask"/>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

taskAffinity属性是迁移后的所指栈。

根据上述Mainfest配置,执行流程:

  1. 首先点击APP图标启动MainActivity,创建一个taskAffinitycom.example.taskb的任务栈,MainActivity入栈。
    启动APP后栈状态
  2. MainActivity启动OtherTaskActivity,那么他还是会在应用的栈中入栈。
    启动OtherTaskActivity
  3. 点击Home,发生Task Reset,应用com.example.taskb任务栈处于后台,由于OtherTaskActivity属性allowTaskReparenting="true" && taskAffinity=".othertask",所以此时这个应用后台将存在两个任务栈。
    两个任务栈
  4. 点击APP图标重新启动应用,com.example.taskb任务栈处于前台,显示MainActivitycom.example.taskb.othertask任务栈处于后台,不显示。当按回退键时,com.example.taskb任务栈清除,com.example.taskb.othertask任务栈回到前台,显示OtherTaskActivity
注意4: taskAffinity起作用只有两种情况
  1. 设置launchMode="singleTask"或者intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  2. 设置allowTaskReparenting=true并满足前面所说的情况。

应用场景:
activity设置SingleTask,退出应用清除栈。适合闪屏页+主页模式,闪屏页为MAIN入口,跳转到主页前finish闪屏页,主页启动模式为SingleTask,可以实现保存应用状态。

4. singleInstance 栈内有且只有一个实例,并可复用

任务栈中只有一个activity,如果存在,那么直接使用实例,调用onNewIntent方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,639评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,093评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,079评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,329评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,343评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,047评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,645评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,565评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,201评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,338评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,014评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,701评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,194评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,685评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,345评论 2 358