【Android】Activity启动模式

【笔记】【Android】Activity启动模式

基本概念

1. Task

一般情况下一个App只有一个 Task,名字为该App的包名。在手机的最近开启的App列表中,每一个 Task 就占据一个位置。即切换应用的基本调度单位为 Task

一个 Task 下包含了一个 Activity栈

2. Activity栈

表示一系列的 Activity,遵循先进后出,后进先出的原则。

3. 图像描述

图片描述

启动模式

AppA

com.bin.appa

AppB

com.bin.appb


各种Activity的属性

StandardActivity

启动模式:standard

是否可跨进程打开:是

指定Task:默认包名

SingleTopActivity

启动模式:singleTop

是否可跨进程打开:是

指定Task:默认包名

SingleTaskActivity

启动模式:singleTask

是否可跨进程打开:是

指定Task:默认包名

SingleInstanceActivity

启动模式:singleInstance

是否可跨进程打开:是

指定Task:默认包名

TaskSingleInstanceActivity

启动模式:singleInstance

是否可跨进程打开:否

指定Task:bin.test.task

TaskSingleTaskActivity

启动模式:singleTask

是否可跨进程打开:否

指定Task:bin.test.task

TaskSingleTopActivity

启动模式:singleTop

是否可跨进程打开:否

指定Task:bin.test.task

TaskStandardActivity

启动模式:standard

是否可跨进程打开:否

指定Task:bin.test.task

1. Standard

默认的启动方式,每次启动该模式的Activity时,都会新建一个实例并加入到当前Task的Activity栈顶。如果是在启动模式为 singleInstance 的Activity中启动,那么分两种情况:

  1. 当前App内存在指定的Task,则直接将该Activity放到Task。
  2. 当前App内不存在指定的Task,则新建一个Task再放入。

就类似于设置了 FLAG_ACTIVITY_NEW_TASK

使用场景

一般情况下都使用该模式启动活动。

adb命令观察

动作:打开AppA,打开AppB。AppA 创建一个 StandardActivity→创建一个 StandardActivity→打开 AppBStandardActivity

预计结果为:AppA中只有一个Task,Task中的Activity栈顶的Activity为 AppBStandardActivity。AppB中只有一个Task,Task中的Activity栈只有一个 MainActivity

使用1观察:

Running activities (most recent first):
      TaskRecord{4971b86 #169 A=com.bin.appa U=0 sz=4}//APP A
        Run #10: ActivityRecord{285089f3 u0 com.bin.appb/.StandardActivity t169}//包名为APP B
        Run #9: ActivityRecord{1fe06e75 u0 com.bin.appa/.StandardActivity t169}
        Run #8: ActivityRecord{a50fe67 u0 com.bin.appa/.StandardActivity t169}
        Run #7: ActivityRecord{3080b171 u0 com.bin.appa/.MainActivity t169}
      TaskRecord{14396a12 #171 A=com.bin.appb U=0 sz=1}//APP B
        Run #6: ActivityRecord{2d90525 u0 com.bin.appb/.MainActivity t171}

2. SingleTop

Activity栈顶模式,启动该模式Activity时,会先检测当前Task 中的Activity栈的栈顶是否为该活动。如果是,则复用该活动,会回调 onNewIntent() 这个生命周期;如果不是,则新建一个该Activity放入当前Task的Activity栈顶。

使用场景

需要先登录才能使用的App,并且不允许账号同时在线。此时可以将登录活动的启动模式设置为 singleTop。这样当账号在其他设备登录时,直接启动登录活动即可。无需担心用户使用“回退键”跳过登录。

adb命令观察

  1. 动作:打开AppA。创建一个 StandardActivity→创建一个 SingleTopActivity→创建一个 SingleTopActivity→创建一个 StandardActivity→创建一个 SingleTopActivity

预计结果:AppA中只有一个Task,Task中的Activity栈由上到下为:

|SingleTopActivity|

|StandardActivity |

|SingleTopActivity|

|StandardActivity |

| MainActivity |

使用2观察:

Running activities (most recent first):
      TaskRecord{13b3903 #172 A=com.bin.appa U=0 sz=5}
        Run #10: ActivityRecord{4b96105 u0 com.bin.appa/.SingleTopActivity t172}
        Run #9: ActivityRecord{38b93877 u0 com.bin.appa/.StandardActivity t172}
        Run #8: ActivityRecord{a1de7d9 u0 com.bin.appa/.SingleTopActivity t172}
        Run #7: ActivityRecord{3fe333ab u0 com.bin.appa/.StandardActivity t172}
        Run #6: ActivityRecord{759b942 u0 com.bin.appa/.MainActivity t172}
  1. 动作:打开AppA。创建一个 StandardActivity→创建一个 SingleTopActivity→使用 FLAG_ACTIVITY_NEW_TASK 创建一个 TaskStandardActivity→创建一个 SingleTopActivity

预计结果:AppA中有两个Task,分别为默认名称为包名的Task和自定义的Task。

包名Task中的Activity栈内由上到下为:

|SingleTopActivity|

|StandardActivity |

| MainActivity |

自定义Task中的Activity栈内由上到下为:

| SingleTopActivity |

|TaskStandardActivity|

 Running activities (most recent first):
      TaskRecord{32dad336 #180 A=bin.test.task U=0 sz=2}//自定义task
        Run #10: ActivityRecord{213784e0 u0 com.bin.appa/.SingleTopActivity t180}
        Run #9: ActivityRecord{2e381c57 u0 com.bin.appa/.TaskStandardActivity t180}
      TaskRecord{26d733a4 #179 A=com.bin.appa U=0 sz=3}//APP A默认task
        Run #8: ActivityRecord{12fdb4b9 u0 com.bin.appa/.SingleTopActivity t179}
        Run #7: ActivityRecord{241a618b u0 com.bin.appa/.StandardActivity t179}
        Run #6: ActivityRecord{113c59c6 u0 com.bin.appa/.MainActivity t179}

3. SingleTask

每次启动该模式的Activity时,会先寻找是否有该Activity指定的Task,默认Task为包名,可通过 taskAffiny 指定名称。如果不存在指定的Task,则新建一个Task并将该Activity放入。如果存在指定的Task,则检查其中是否有该Activity。如果有,则移除它上面的所有Activity;如果没有,则将该Activity放入栈顶。

该启动模式的Activity所处的Activity栈内,只存在一个该Activity。

使用场景

如微信小程序,需要在最近任务列表中显示小程序和微信两个卡片。并且小程序中有自己的一套Activity栈。

这个只是我的假设,不一定微信小程序就是这么实现的。

adb命令观察

  1. 动作:打开AppA。创建一个 StandardActivity→通过 FLAG_ACTIVITY_NEW_TASK 创建一个 TaskStandardActivityt→创建一个 TaskSingleTaskActivity→创建一个 StandardActivity→通过最近任务列表返回第一个 StandardActivity→创建一个 TaskSingleTaskActivity

预计结果:AppA有2个Task,一个名称为包名,一个的名称为 bin.test.task

包名Task中的Activity栈由上到下为:

| StandardActivity |

| MainActivity |

自定义Task中的Activity栈由上到下为:

|TaskSingleTaskActivity|

| TaskStandardActivity |

  Running activities (most recent first):
      TaskRecord{1314e94e #190 A=bin.test.task U=0 sz=2}
        Run #9: ActivityRecord{1e82e908 u0 com.bin.appa/.TaskSingleTaskActivity t190}
        Run #8: ActivityRecord{31e6273e u0 com.bin.appa/.TaskStandardActivity t190}
      TaskRecord{3b24b37c #189 A=com.bin.appa U=0 sz=2}
        Run #7: ActivityRecord{3166f6a8 u0 com.bin.appa/.StandardActivity t189}
        Run #6: ActivityRecord{17c5806 u0 com.bin.appa/.MainActivity t189}

4. SingleInstance

启动该模式的Activity时,检测所有Task内是否存在该Activity。如果有,则回调 onNewIntent(),并将该Task移动到前台;如果没有,则新建一个Task并将该Activity放入栈中。

该模式的Activity独享一个Task。

使用场景

如地图类应用,需要提供给第三方App调起地图。

adb命令观察

动作:打开AppA。创建一个 StandardActivity→创建一个 SingleInstanceActivity→创建一个 StandardActivity→创建一个 SingleInstanceActivity

预计结果:AppA中存在两个Task,两个Task的名称一致。

第一个Task中的Activity栈由上到下为:

|SingleInstanceActivity|

第二个Task中的Activity栈由上到下为:

|StandardActivity|

|StandardActivity|

| MainActivity |

 Running activities (most recent first):
      TaskRecord{2754349 #193 A=com.bin.appa U=0 sz=1}
        Run #9: ActivityRecord{39dd2b16 u0 com.bin.appa/.SingleInstanceActivity t193}
      TaskRecord{6a0996f #191 A=com.bin.appa U=0 sz=3}
        Run #8: ActivityRecord{39b42723 u0 com.bin.appa/.StandardActivity t191}
        Run #7: ActivityRecord{50225c0 u0 com.bin.appa/.StandardActivity t191}
        Run #6: ActivityRecord{14dedf63 u0 com.bin.appa/.MainActivity t191}

总结

四个启动模式可以分成两类,第一类是 standardsingleTop,它们都可以存在多个实例;第二类是 singleTasksingleInstance,它们只会存在一个实例。

多实例 单实例
stadard singleTask
singleTop singleInstance

为什么有了Activity栈后还要有Task存在

主要是为了方便多个App之间互相调用时,有无缝的体验感。比如在写日记的时候,可以调起系统相机进行拍照,拍完之后还能进入相册选照片。这一系列的操作,都如同在一个日记App内完成的一样。这就是Task存在的目的。


  1. adb shell dumpsys activity activities 
  2. adb shell dumpsys activity activities 
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇