请解释 Android 中四种启动模式(standard, singleTop, singleTask, singleInstance)的区别和适用场景
解读
国内大厂面试时,这道题几乎必问,但面试官真正想听的不是“官方定义”,而是“你在真实业务里怎么选、怎么踩坑、怎么兜底”。
因此回答思路要“先结论、后原理、再案例、再坑点”,用“一句话区别 + 一句话原理 + 一句话场景 + 一句话坑”四段式展开,既体现深度又控制时长。
注意:国内项目普遍接多渠道 SDK、深度定制 ROM,要把“任务栈被厂商魔改”这一现实考虑进去,否则会被追问“为什么 singleTask 在小米上失效”。
知识点
- 任务栈(Task)与 ActivityRecord:AMS 管理的历史栈单元,每个 Task 对应一个 Stack,启动模式决定新 Activity 实例与 Task 的归属关系。
- Intent.FLAG_ACTIVITY_* 与 launchMode 的叠加规则:代码动态 flag 优先级高于 manifest 静态声明,国内很多推送 SDK 偷偷加 FLAG_NEW_TASK,会把你的 singleTop 冲掉。
- clearTop 与 reorder 行为:singleTask 自带 CLEAR_TOP 语义,但国产 ROM 可能把 TaskAffinity 重置,导致回不到旧栈。
- 复用生命周期回调:singleTop 的 onNewIntent、singleTask 的 onNewIntent + onActivityResult 失效场景(Android 10 之后 startActivityForResult 被废弃,需用 Activity Result API)。
- 折叠屏/多窗口下的栈可见性:singleInstance 在副屏打开时,某些 ROM 会强制把实例挪回主屏,导致透明主题闪屏。
- 国内厂商“保活”陷阱:singleInstance 被系统单独放一栈,容易被省电策略杀掉,推送到达率反而下降。
答案
-
standard
一句话区别:每次启动必创全新实例,无论栈内是否已有。
原理:AMS 在调用者所在 Task 顶部直接新建 ActivityRecord,生命周期完整走 onCreate→onStart→onResume。
场景:普通二级页面,如商品详情、文章页,允许无限层级回退。
坑:快速双击时瞬间压两实例,需在 onCreate 做防抖或 launchMode 临时改 singleTop。 -
singleTop
一句话区别:栈顶复用,非栈顶仍创实例。
原理:AMS 发现目标 Task 栈顶已存在该 ActivityRecord,则走 onNewIntent,不弹新实例;否则同 standard。
场景:搜索页、扫码页,防止推送/通知反复打开多层。
坑:国内推送 SDK 默认加 FLAG_ACTIVITY_NEW_TASK,会把当前页挪到新 Task,singleTop 失效;需在 receiver 里清空 flag 或强制 Intent.FLAG_ACTIVITY_CLEAR_TOP。 -
singleTask
一句话区别:全局单例,所在 Task 只允许一个实例,启动时自动清掉其上方所有 Activity。
原理:AMS 先按 TaskAffinity 找对应 Task,找到后把目标实例提到栈顶并弹掉上方所有 Activity,触发 onNewIntent;若 Task 不存在则新建 Task 再新建实例。
场景:应用首页、WebView 容器、播放器,保证回首页时一次性清空中转页。
坑:小米/华为 ROM 对 TaskAffinity 做“魔改合并”,可能出现首页被拉到后台 Task,导致 singleTask 重建;兜底方案:首页 android:taskAffinity="" 强制默认包名,配合 Activity Result API 处理回调。 -
singleInstance
一句话区别:系统级单例,独占新 Task 且该 Task 永不放入其他 Activity。
原理:AMS 新建独立 Task,taskType 为 SINGLE_INSTANCE,最近任务列表里单独卡片;任何其他 Activity 启动都会另开 Task。
场景:系统来电、悬浮窗、全局投屏控制面板,需要与主应用完全隔离。
坑:国内 ROM 省电策略优先杀“孤立 Task”,singleInstance 实例易被回收;且透明主题在折叠屏切换时闪黑;建议只在真正需要跨进程可见的组件使用,并加前台 Service 保活。
一句话总结选型口诀:
“普通页 standard,顶部复用 singleTop,首页根 singleTask,系统框 singleInstance。”
拓展思考
- Android 12 的“多实例会话”特性允许同一 Activity 以不同 session 多次出现在最近任务,launchMode 与 android:documentLaunchMode、android:maxRecents 如何协同?
- 在 Jetpack Navigation 单 Activity 架构下,launchMode 实际由 NavHostFragment 托管,Fragment 的“栈顶复用”能否用自定义 Navigator 实现 singleTop 效果?
- 国内小程序容器(微信、支付宝)把 Activity 做成 singleInstance,再用 IActivityManager.addAppTask 伪造最近任务卡片,如何规避 10 秒后台启动限制?
- 车载 Android(AAOS)对 singleInstance 做了“悬浮 Task”级别提升,允许在副驾屏常驻,如何兼容手机 APK 直接上车机而不改 launchMode?
- 隐私沙盒(Privacy Sandbox)限制 cross-task 启动,singleTask 的 TaskAffinity 匹配规则未来可能收紧,如何提前用 PendingIntent 封装跳转以降低适配成本?
答到这一层,面试官一般会收手,并给你打“熟悉系统源码、有国内落地经验”的标签。