Android 四大组件 - 复习与面试题

5 阅读8分钟

Android 四大组件 - 复习与面试题

适合 1~3 年经验复习。先掌握概念边界,再背高频题的回答结构。


一、总览:四大组件分别解决什么问题

  1. Activity:负责界面展示与用户交互,是 UI 入口。
  2. Service:负责无界面的后台任务(不等于子线程)。
  3. BroadcastReceiver:负责接收和分发系统/应用广播,做轻量事件响应。
  4. ContentProvider:负责跨进程、结构化数据共享,统一数据访问接口。

一句话:Activity 管界面,Service 管后台能力,Receiver 管事件通知,Provider 管数据共享。


二、Activity 高频面试题

1) Activity 启动模式有哪几种?区别是什么?

考点:任务栈管理、复用规则、面试中的真实场景。

答案要点

  • standard:默认模式,每次启动都创建新实例。
  • singleTop:若目标 Activity 在栈顶则复用并回调 onNewIntent,否则新建。
  • singleTask:任务栈中已有实例则复用并清除其上方页面,回调 onNewIntent
  • singleInstance:独占任务栈,系统中仅一个实例(现在常见度低,了解即可)。

面试补充:常用的是 standard/singleTop/singleTask,要结合 taskAffinityFLAG_ACTIVITY_NEW_TASK 一起谈。

1.1) taskAffinityFLAG_ACTIVITY_NEW_TASK 到底怎么配合?

先记三个概念

  • taskAffinity:Activity “更倾向属于哪个任务栈”的标签(默认是应用包名)。
  • FLAG_ACTIVITY_NEW_TASK:启动时要求“放到一个任务栈里(必要时新建)”,不是简单“新建 Activity”。
  • 启动模式(standard/singleTop/singleTask):决定目标 Activity 在该任务栈里是否复用。

常见规则(面试可直接说)

  1. 不加 NEW_TASK:通常在当前任务栈内启动,taskAffinity 基本不参与决策。
  2. 加了 NEW_TASK:系统会尝试找“可复用的任务栈”(与目标 Activity 的 affinity 匹配);找不到才新建任务栈。
  3. 若目标是 singleTask:在目标任务栈内若已有实例,会走复用 + onNewIntent,并清掉其上方页面。

高频易错点

  • taskAffinity 本身不会主动“把 Activity 丢到别的栈”,通常要配合 NEW_TASK 才更明显生效。
  • NEW_TASK 不是“每次都新建一个栈”,它是“先找可用栈,找不到再新建”。
  • 同一进程内也可能出现多个任务栈(如深链、桌面入口、多任务回流场景)。

面试示例(简版)

  • B 配置了不同于默认的 taskAffinity,A 启 B 时加 FLAG_ACTIVITY_NEW_TASK
    系统会优先找 affinity 匹配 B 的任务栈,有则把 B 放进去(或复用),没有才创建新任务栈。

一句话taskAffinity 决定“偏向哪个栈”,NEW_TASK 决定“按任务栈维度启动”,启动模式决定“进栈后是新建还是复用”。

1.2) launchModeIntent Flag,谁优先?

结论:两者都会参与计算,但在同类能力冲突时,本次启动的 Intent Flag 通常优先于 Manifest 的 launchMode

可直接背的规则

  1. 不带相关 Flag:按 Manifest 的 launchMode 走(静态默认策略)。
  2. 带了相关 Flag:按本次 Intent 的 Flag 约束计算(动态指令优先)。
  3. 不冲突时:组合生效(例如 Flag 影响任务栈,launchMode 影响实例复用)。

示例

  • 目标 Activity 是 standard,但启动时加了 FLAG_ACTIVITY_NEW_TASK,本次会按 NEW_TASK 的任务栈规则处理。
  • 目标 Activity 是 singleTop,再加 FLAG_ACTIVITY_SINGLE_TOP,语义一致,属于显式强化本次启动行为。

一句话launchMode 是默认配置,Intent Flag 是本次命令;本次命令通常优先。


1.3) Activity 常见 Intent Flag 速查(面试高频)

Flag作用常见场景
FLAG_ACTIVITY_NEW_TASK按任务栈维度启动,优先复用任务栈,找不到再新建通知点击拉起页面、跨应用启动
FLAG_ACTIVITY_SINGLE_TOP若目标在栈顶则复用,回调 onNewIntent防止重复打开同页
FLAG_ACTIVITY_CLEAR_TOP若栈中已有目标,清除其上方 Activity,再把目标拉到前台返回主页/主容器页
FLAG_ACTIVITY_CLEAR_TASK清空目标任务栈中的所有页面(通常配合 NEW_TASK退出登录后重建首页栈
FLAG_ACTIVITY_NO_HISTORY页面不进入历史栈,离开后通常不可回退一次性引导页、短流程页
FLAG_ACTIVITY_REORDER_TO_FRONT若目标已在栈中,把它调到前台(不清上方)在栈内快速唤回已有页
FLAG_ACTIVITY_MULTIPLE_TASK允许创建多个任务实例(通常配合 NEW_TASK特殊多任务场景,慎用

高频组合(建议背)

  1. NEW_TASK + CLEAR_TASK:重置任务栈,常用于登录态切换后进入首页。
  2. CLEAR_TOP + SINGLE_TOP:回到已有目标页并复用,避免重复创建。
  3. NEW_TASK + SINGLE_TOP:从外部拉起时,若目标恰好在新任务栈顶可复用。

易踩坑

  • CLEAR_TASK 基本要和 NEW_TASK 一起用,单独使用常不符合预期。
  • CLEAR_TOP 是否新建目标实例,和目标 launchMode / 是否栈顶有关,不是永远只回调 onNewIntent
  • NEW_TASK 不是“每次新建栈”,而是“先找可复用任务栈”。

一句话:先确定“任务栈策略”(NEW_TASK/CLEAR_TASK),再看“实例复用策略”(SINGLE_TOP/CLEAR_TOP/launchMode)。


2) Activity 生命周期完整流程?哪些方法最容易被追问?

标准流程(冷启动)onCreate -> onStart -> onResume

从前台到后台onPause -> onStop

回到前台onRestart -> onStart -> onResume

销毁onPause -> onStop -> onDestroy

追问高频点

  • onPause 是否能做耗时操作?(不建议,影响切换流畅度)
  • onSaveInstanceState(stop前)onRestoreInstanceState(start 后) 何时触发?
  • 配置变更(如旋转)为何会重建 Activity?

3) onSaveInstanceState 和 ViewModel 的区别?

答案要点

  • onSaveInstanceState:用于进程可能被杀后的短期状态恢复(Bundle,体积受限)。
  • ViewModel:用于配置变更下的数据保留(如旋转不丢),不是持久化方案。

一句话:ViewModel 抗重建,savedInstanceState 抗进程回收。


4) Activity A 跳 B 再返回,生命周期怎么走?

答案要点(常规不透明 B)

  • A 启动 B:A onPause -> onStop,B onCreate -> onStart -> onResume
  • 返回 A:B onPause -> onStop -> onDestroy,A onRestart -> onStart -> onResume

三、Service 高频面试题

1) Service 是不是运行在子线程?

标准答案:不是。Service 默认运行在主线程。
耗时任务必须自己切线程(如线程池、协程、HandlerThread),否则会卡主线程甚至 ANR。


2) startService 和 bindService 区别?

答案要点

  • startService:强调“启动执行”,调用方不关心返回接口;需手动 stopSelf/stopService
  • bindService:强调“客户端-服务端交互”,通过 IBinder 暴露能力;绑定方都解绑后可销毁。
  • 可同时 start + bind,销毁要同时满足对应条件。

3) 前台服务(Foreground Service)为什么要存在?

答案要点

  • Android 后台限制越来越严格,长时任务需提升可见性。
  • 前台服务要求常驻通知,告诉用户“任务正在进行”。
  • 场景:导航、音乐播放、运动记录、蓝牙持续连接等。

4) IntentService 为什么不推荐了?

答案要点

  • IntentService 基于串行队列 + 工作线程,模型简单但能力有限。
  • 新项目更推荐 WorkManager / 协程 + 前台服务等现代方案。

四、BroadcastReceiver 高频面试题

1) 广播分类和区别?

答案要点

  • 普通广播:异步分发,接收者间无优先级串行结果传递。
  • 有序广播:按优先级串行,可中断、可传递结果(新版本限制更多,需看场景)。
  • 本地广播:只在应用内(LocalBroadcastManager 已不推荐,常用其他事件总线替代)。

2) 静态注册和动态注册区别?

答案要点

  • 静态注册:AndroidManifest 中声明;应用未启动时也可能被系统拉起(受系统限制)。
  • 动态注册:代码中 registerReceiver,生命周期可控;不用时必须 unregisterReceiver 避免泄漏。

3) onReceive 里能做耗时操作吗?

标准答案:不建议。onReceive 执行时间很短,做耗时会触发 ANR 风险。
正确做法:快速返回,把任务转给 Service/WorkManager/线程池。


五、ContentProvider 高频面试题

1) ContentProvider 解决什么问题?

答案要点

  • 跨进程数据共享与访问控制。
  • 统一 CRUD 接口:query/insert/update/delete
  • 通过 content:// URI 定位资源。

2) 为什么说 ContentProvider 底层也走 Binder?

答案要点

  • 调用方通过 ContentResolver 访问 Provider。
  • 若跨进程,实际通过 Binder IPC 调用目标进程 Provider。
  • 对开发者暴露的是统一 URI/CRUD 抽象,屏蔽了 IPC 细节。

3) Provider 的权限控制怎么做?

答案要点

  • readPermission / writePermission
  • grantUriPermissions
  • 针对特定路径配置权限(path-permission

六、组合题(非常高频)

1) 四大组件的启动过程最终都经过谁?

参考答法: 都不是“组件自己直接启动自己”,最终都通过系统服务(AMS/ATMS 等)调度,应用进程侧由 ActivityThread 接收调度并回调到对应组件生命周期。


2) 四大组件都要注册到 Manifest 吗?

参考答法

  • Activity / Service / Receiver / Provider 原则上都需要在 Manifest 声明(除少量动态注册 Receiver)。
  • Android 12+ 对 exported 有强约束:有 intent-filter 的组件必须显式声明 android:exported

3) 进程被杀后,哪些状态容易丢?怎么保?

参考答法

  • Activity 临时 UI 状态:savedInstanceState
  • 业务缓存:本地数据库/文件/SP
  • 长任务:WorkManager 或前台服务恢复策略

七、面试速记(30 秒版)

  1. 四大组件分别负责 UI、后台能力、事件分发、数据共享。
  2. Activity 重点背:生命周期 + 启动模式 + 状态恢复。
  3. Service 重点背:默认主线程、start/bind 区别、前台服务场景。
  4. Receiver 重点背:动态/静态注册、onReceive 不做耗时。
  5. Provider 重点背:URI + ContentResolver + Binder + 权限控制。

八、建议练习方式

  1. 先背“30 秒版”总纲,保证开口有结构。
  2. 每个组件挑 2 道高频题,按“定义-场景-风险-解决”四句模板练回答。
  3. 结合你项目经历补 1 个真实案例(如:前台服务保活、Receiver 泄漏排查、Activity 重建恢复)。