一、Activity 基础生命周期
1. Activity 完整生命周期有哪些方法?各自触发场景?
答案:共 7 个
- onCreate:页面首次创建,只执行一次,初始化布局、变量、控件。
- onStart:页面变为可见,还不能交互。
- onResume:页面到前台,获取焦点,可正常交互。
- onPause:页面被遮挡、弹窗弹出,失去焦点,适合保存轻量数据。
- onStop:页面完全不可见,退后台或被覆盖。
- onRestart:从后台切回前台,由 Stop 变为 Start。
- onDestroy:页面销毁,释放资源、解绑监听、关闭流。
2. 横竖屏切换 Activity 生命周期怎么走?怎么避免重建?
答案 :默认:销毁旧 Activity → 重新创建新 Activity,走完整生命周期。
避免重建:在清单文件配置 android:configChanges="orientation|screenSize",切换时不重建 ,只回调 onConfigurationChanged。
3. 后台内存不足时 Activity 会怎样?onSaveInstanceState 什么时候调用?
答案 :系统会回收销毁后台 Activity;
onSaveInstanceState 在 横竖屏切换、退后台、内存不足即将回收前调用,用于保存临时状态数据,重建后可在 onCreate 恢复。
4. 从 A 页面跳到 B 页面,A 和 B 生命周期执行顺序?
A.onPause → B.onCreate → B.onStart → B.onResume → A.onStop
5. 应用退到后台、再切回前台生命周期变化?
退后台:onPause → onStop切回前台:
onRestart → onStart → onResume
二、Activity 四种启动模式
1. 说说 Standard、singleTop、singleTask、singleInstance 四种启动模式区别和应用场景?
-
standard 默认:每次跳转都新建实例,重复打开重复入栈;适合普通详情页。
-
singleTop 栈顶复用:目标 Activity 在栈顶就复用,不走 onCreate,回调 onNewIntent;不在栈顶则新建;适合登录页、推送跳转页。
-
singleTask 栈内唯一 :栈内只保留一个实例,已存在就把它上面所有 Activity 全部出栈,自身置栈顶;适合首页、主页。
-
singleInstance 全局唯一:单独独占一个任务栈,全局只有一个实例,和其他页面隔离;适合来电弹窗、闹钟页面。
2. singleTask 的栈内复用原理?会销毁上面所有 Activity 吗?
答案:
检测任务栈中是否已存在该 Activity 实例;存在则把它之上所有 Activity 全部出栈销毁,复用原有实例,回调 onNewIntent。
3. singleInstance 单独任务栈特点?适用什么业务?
答案:
单独开辟独立任务栈,全局唯一实例,其他 Activity 不能进入该栈;适合系统弹窗、来电界面、悬浮独立页面。
4. 跳转页面如何指定启动模式?XML 和代码两种方式?
答案:
XML:在 AndroidManifest 对应 activity 标签加 android:launchMode;
代码:Intent 设置 addFlags() 如 FLAG_ACTIVITY_SINGLE_TOP 等。
5. singleTop 栈顶复用什么时候生效?不在栈顶会怎样?
答案:
只有目标 Activity正好在任务栈栈顶才复用;若在栈中间或底部,直接新建实例入栈。
三、任务栈 & 返回栈
1. 什么是任务栈?App 退出和任务栈什么关系?
答案:
任务栈是存放 Activity 实例的先进后出返回栈;打开页面入栈,返回键出栈;清空整个任务栈就退出 App。
2. 为什么按返回键会依次退出页面?任务栈入栈出栈规则?
答案:
页面打开压栈 ,返回键弹栈,遵循后进先出,所以一层层倒退关闭。
3. 应用多开、跳转第三方 App,任务栈怎么变化?
答案:
跳转第三方会新建另一个任务栈;应用多开各自独立任务栈,互不干扰。
4. clearTop、clearTask、singleTask 清空栈的区别?
答案:
- FLAG_ACTIVITY_CLEAR_TOP:复用目标 Activity,销毁它上面所有页面。
- FLAG_ACTIVITY_CLEAR_TASK:清空整个原有任务栈,再新建目标页面。
- singleTask:自带 clearTop 效果,栈内复用并清上层页面。
5. 如何彻底退出 App、清空整个任务栈?
答案:
循环关闭所有 Activity、使用 finishAffinity()、设置 flag 清空任务栈再退出。
四、Activity 三种启动:冷 / 温 / 热启动
1. 分别说说冷启动、温启动、热启动的区别和触发场景?
答案:
- 冷启动:进程不存在,需新建进程 + 初始化 Application + 重建 Activity;场景:首次打开、后台进程被杀、手机重启。
- 温启动:进程还在,Activity 被系统回收,只需重建 Activity,不用初始化 Application。
- 热启动:App 在后台,进程和 Activity 都没销毁,只需从后台切前台。
2. 冷启动完整流程从点击图标到页面显示经历哪些步骤?
答案:
点击图标→系统创建新进程→初始化 Application→创建 ActivityThread→启动目标 Activity→走生命周期→加载解析布局→绘制 UI→显示页面。
3. 冷启动为什么最慢?瓶颈一般在哪?
答案:
要新建进程、初始化 App、全量走 Activity 生命周期、加载布局资源;瓶颈多在 Application 主线程初始化太多 SDK、Activity onCreate 做耗时操作、布局嵌套复杂。
4. 怎么判断 App 当前是冷启动还是热启动?
答案:
记录 App 前后台状态、进程存活状态、Activity 重建标记;也可通过启动耗时、是否初始化 Application 来区分。
五、Activity 启动速度优化(高级必问)
1. App 冷启动卡顿常见原因有哪些?
答案:
Application 主线程初始化大量 SDK、onCreate 做网络 / IO / 复杂计算、布局嵌套太深、冗余 View 过多、主线程阻塞、频繁 GC。
2. 如何优化 Application 初始化?怎么懒加载、异步初始化 SDK?
答案:
非必要 SDK 不主动初始化;放到子线程异步初始化;用到时再懒加载;避免在 attachBaseContext、onCreate 做耗时操作。
3. onCreate 里哪些操作不能做?耗时业务放哪里?
答案:
不能做网络请求、数据库查询、大文件 IO、复杂循环计算;耗时全部放到子线程、协程、线程池异步执行。
4. 布局优化有哪些手段?ConstraintLayout、ViewStub、减少嵌套?
答案:
减少 LinearLayout 多层嵌套,多用 ConstraintLayout 约束布局;用 ViewStub 懒加载非首屏布局;删除无用冗余 View、减少过度绘制、减少 inflate 耗时。
5. 如何解决启动白屏、黑屏问题?原理是什么?
答案:
给 Activity 主题设置窗口背景占位图;原理是 App 未完全渲染前,先用主题背景临时占位,避免空白视觉。
6. 首屏骨架屏、占位图优化思路?
答案:
先展示骨架屏 / 默认占位布局,异步请求数据,数据返回后再替换真实内容,提升视觉秒开体验。
7. 主线程哪些行为会拖慢启动?怎么排查主线程耗时?
答案:
使用 StrictMode 严苛模式、Android Studio Profiler、打印主线程耗时日志、查看 ANR 日志卡顿堆栈,定位耗时代码。
六、Fragment 高频面试
1. Fragment 生命周期和 Activity 关联关系?
答案:
Fragment 生命周期依附宿主 Activity,Activity 生命周期变化会同步带动 Fragment 触发对应生命周期。
2. add、replace、attach/detach 区别?各自生命周期变化?
答案:
- add:添加 Fragment 到容器,不销毁原有 Fragment,页面叠加。
- replace:销毁移除旧 Fragment,替换为新的。
- attach/detach:分离时不销毁实例,只分离视图,重新附着恢复视图。
3. Fragment 懒加载实现方式?为什么要懒加载?
答案:
根据 Fragment 是否对用户可见再请求网络;目的是避免 ViewPager 预加载浪费流量、造成多余请求和性能消耗。
4. Fragment 重叠问题怎么产生?如何解决?
答案:
横竖屏切换、系统异常重启重复创建 Fragment 导致重叠;
解决:保存状态、判空复用已有实例、不要重复 add。
5. ViewPager + Fragment 预加载怎么禁止?懒加载最佳实践?
答案:
禁止 offscreenPageLimit 预加载,结合 Fragment 可见性回调,只有对用户可见时才执行网络请求和数据渲染。
6. Fragment 通信方式有哪几种?优缺点?
答案:
接口回调、ViewModel 共享数据、Bundle 传值、EventBus / 广播;接口解耦干净、ViewModel 适合跨 Fragment 共享、EventBus 便捷但需注意生命周期防泄漏。
七、附加深挖面试题(高级必问)
1. Activity 启动过程底层原理(AMS、ActivityThread 简单说下)
AMS 是系统总指挥,负责调度和管控;ActivityThread 是 App 内部执行者,负责创建 Activity、走生命周期、驱动 UI 渲染,两者通过 Binder 跨进程通信完成 Activity 启动。
面试极简背诵版
用户点击图标后,Launcher 请求 AMS;AMS 发现进程不存在就创建 App 进程,进程启动后初始化 ActivityThread 并开启主线程消息循环;AMS 通过 Binder 通知 ActivityThread,反射创建 Activity 实例,由 ActivityThread 调度执行完整生命周期,最终完成页面加载和显示。
2. Intent 传递数据大小限制?超出会怎样?怎么解决?
答案:
Binder 通信限制约 1MB,超出会闪退、报错;
解决:传递 ID、全局静态缓存、文件路径、数据库存主键,不直接传大数据。
3. Activity 之间大量数据传递有哪些方案?
- 全局静态变量 / 单例缓存
- Application 全局缓存
- 序列化存本地 / 数据库
- EventBus / LiveData 事件通信 5.接口回调 / 共享 ViewModel(同进程)
因为 Intent 受 Binder 1M 大小限制,不能传大数据;大量数据传递常用:
全局静态 / 单例缓存、Application 缓存、本地文件 / 数据库序列化、EventBus、共享 ViewModel ,优先用单例缓存或 ViewModel,用完及时清空防泄漏。
4. 为什么不建议在 Application 主线程做耗时初始化?
答案:
会阻塞主线程,拉长冷启动时间,容易造成启动卡顿、甚至 ANR。