Android 四大组件 - 复习与面试题
适合 1~3 年经验复习。先掌握概念边界,再背高频题的回答结构。
一、总览:四大组件分别解决什么问题
- Activity:负责界面展示与用户交互,是 UI 入口。
- Service:负责无界面的后台任务(不等于子线程)。
- BroadcastReceiver:负责接收和分发系统/应用广播,做轻量事件响应。
- ContentProvider:负责跨进程、结构化数据共享,统一数据访问接口。
一句话:Activity 管界面,Service 管后台能力,Receiver 管事件通知,Provider 管数据共享。
二、Activity 高频面试题
1) Activity 启动模式有哪几种?区别是什么?
考点:任务栈管理、复用规则、面试中的真实场景。
答案要点:
standard:默认模式,每次启动都创建新实例。singleTop:若目标 Activity 在栈顶则复用并回调onNewIntent,否则新建。singleTask:任务栈中已有实例则复用并清除其上方页面,回调onNewIntent。singleInstance:独占任务栈,系统中仅一个实例(现在常见度低,了解即可)。
面试补充:常用的是 standard/singleTop/singleTask,要结合 taskAffinity、FLAG_ACTIVITY_NEW_TASK 一起谈。
1.1) taskAffinity、FLAG_ACTIVITY_NEW_TASK 到底怎么配合?
先记三个概念:
taskAffinity:Activity “更倾向属于哪个任务栈”的标签(默认是应用包名)。FLAG_ACTIVITY_NEW_TASK:启动时要求“放到一个任务栈里(必要时新建)”,不是简单“新建 Activity”。- 启动模式(
standard/singleTop/singleTask):决定目标 Activity 在该任务栈里是否复用。
常见规则(面试可直接说) :
- 不加
NEW_TASK:通常在当前任务栈内启动,taskAffinity基本不参与决策。 - 加了
NEW_TASK:系统会尝试找“可复用的任务栈”(与目标 Activity 的 affinity 匹配);找不到才新建任务栈。 - 若目标是
singleTask:在目标任务栈内若已有实例,会走复用 +onNewIntent,并清掉其上方页面。
高频易错点:
taskAffinity本身不会主动“把 Activity 丢到别的栈”,通常要配合NEW_TASK才更明显生效。NEW_TASK不是“每次都新建一个栈”,它是“先找可用栈,找不到再新建”。- 同一进程内也可能出现多个任务栈(如深链、桌面入口、多任务回流场景)。
面试示例(简版) :
- B 配置了不同于默认的
taskAffinity,A 启 B 时加FLAG_ACTIVITY_NEW_TASK。
系统会优先找 affinity 匹配 B 的任务栈,有则把 B 放进去(或复用),没有才创建新任务栈。
一句话:taskAffinity 决定“偏向哪个栈”,NEW_TASK 决定“按任务栈维度启动”,启动模式决定“进栈后是新建还是复用”。
1.2) launchMode 和 Intent Flag,谁优先?
结论:两者都会参与计算,但在同类能力冲突时,本次启动的 Intent Flag 通常优先于 Manifest 的 launchMode。
可直接背的规则:
- 不带相关 Flag:按 Manifest 的
launchMode走(静态默认策略)。 - 带了相关 Flag:按本次
Intent的 Flag 约束计算(动态指令优先)。 - 不冲突时:组合生效(例如 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) | 特殊多任务场景,慎用 |
高频组合(建议背) :
NEW_TASK + CLEAR_TASK:重置任务栈,常用于登录态切换后进入首页。CLEAR_TOP + SINGLE_TOP:回到已有目标页并复用,避免重复创建。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,BonCreate -> onStart -> onResume - 返回 A:B
onPause -> onStop -> onDestroy,AonRestart -> 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/writePermissiongrantUriPermissions- 针对特定路径配置权限(
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 秒版)
- 四大组件分别负责 UI、后台能力、事件分发、数据共享。
- Activity 重点背:生命周期 + 启动模式 + 状态恢复。
- Service 重点背:默认主线程、start/bind 区别、前台服务场景。
- Receiver 重点背:动态/静态注册、onReceive 不做耗时。
- Provider 重点背:URI + ContentResolver + Binder + 权限控制。
八、建议练习方式
- 先背“30 秒版”总纲,保证开口有结构。
- 每个组件挑 2 道高频题,按“定义-场景-风险-解决”四句模板练回答。
- 结合你项目经历补 1 个真实案例(如:前台服务保活、Receiver 泄漏排查、Activity 重建恢复)。