1、熟练掌握 Activity/Fragment 生命周期、任务栈、启动模式、冷热温启动原理及启动速度优化

32 阅读10分钟

一、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. clearTopclearTasksingleTask 清空栈的区别?

答案

  • FLAG_ACTIVITY_CLEAR_TOP:复用目标 Activity,销毁它上面所有页面。
  • FLAG_ACTIVITY_CLEAR_TASK:清空整个原有任务栈,再新建目标页面。
  • singleTask:自带 clearTop 效果,栈内复用并清上层页面。

5. 如何彻底退出 App、清空整个任务栈?

答案

循环关闭所有 Activity、使用 finishAffinity()、设置 flag 清空任务栈再退出。

finish ()和finishAffinity() 的区别

  • finish() :关闭当前页面,回到上一页
  • finishAffinity() :关闭整个栈所有页面,直接退出应用

效果:页面栈:A → B → C → D

调用 D.finishAffinity ()

四、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 日志卡顿堆栈,定位耗时代码。

8.androidx.startup 官方启动库

androidx.startup:startup-runtimeJetpack 官方应用初始化框架,专门统一管理 App 启动时所有 SDK、组件的初始化,替代传统在 Application 里一堆手动初始化 的写法。

优势(面试必说)

  • 统一收敛所有初始化逻辑,代码整洁
  • 自动处理任务依赖,不用手动控制顺序
  • 减少多个 ContentProvider 带来的启动耗时
  • 可控制是否自动初始化,支持懒加载、按需初始化
  • 主线程可管控,配合异步任务做启动优化
面试一句话总结

AndroidX Startup 是官方启动初始化框架,统一管理所有 SDK 和组件初始化,自动处理任务依赖、合并减少多余 ContentProvider,避免 Application 臃肿,支持自动和按需初始化,有效优化 App 冷启动速度和架构整洁度。

六、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 之间大量数据传递有哪些方案?

  1. 全局静态变量 / 单例缓存
  2. Application 全局缓存
  3. 序列化存本地 / 数据库
  4. EventBus / LiveData 事件通信 5.接口回调 / 共享 ViewModel(同进程)

因为 Intent 受 Binder 1M 大小限制,不能传大数据;大量数据传递常用:

全局静态 / 单例缓存、Application 缓存、本地文件 / 数据库序列化、EventBus、共享 ViewModel,优先用单例缓存或 ViewModel,用完及时清空防泄漏。

4. 为什么不建议在 Application 主线程做耗时初始化?

答案

会阻塞主线程,拉长冷启动时间,容易造成启动卡顿、甚至 ANR。

5. Android 四大组件

Android 四大组件分别是:Activity、Service、BroadcastReceiver、ContentProvider

1. Activity

负责界面展示、用户交互,是所有 UI 页面的载体,管理页面生命周期。

2. Service

无界面后台运行,用于后台耗时任务、音乐播放、定位、常驻后台等,不参与 UI 交互。

3. BroadcastReceiver 广播接收器

用于系统或应用间通信,监听系统广播(开机、网络变化、电量变化)和自定义广播,组件之间解耦通信。

4. ContentProvider 内容提供者

负责跨应用数据共享,统一管理 App 私有数据,对外提供增删改查接口,比如通讯录、媒体库数据都是通过它共享。

一句话面试完整版

Android 四大组件是 Activity 负责页面 UI 交互、Service 后台无界面任务、BroadcastReceiver 广播通信解耦、ContentProvider 跨应用数据共享