文章目录
- 学习建议
- [基础层(7 题)](#基础层(7 题))
-
- [#1 Jetpack 是什么?包含哪些核心组件? ⭐](#1 Jetpack 是什么?包含哪些核心组件? ⭐)
- [#2 Lifecycle 是什么?LifecycleOwner 和 LifecycleObserver 怎么协作? 🔥](#2 Lifecycle 是什么?LifecycleOwner 和 LifecycleObserver 怎么协作? 🔥)
- [#3 ViewModel 的作用是什么?为什么能跨配置变更存活? 🔥](#3 ViewModel 的作用是什么?为什么能跨配置变更存活? 🔥)
- [#4 LiveData 是什么?有什么特点? ⭐](#4 LiveData 是什么?有什么特点? ⭐)
- [#5 LiveData 和 RxJava Observable 有什么区别? 🔥](#5 LiveData 和 RxJava Observable 有什么区别? 🔥)
- [#6 Navigation 组件解决什么问题? ⭐](#6 Navigation 组件解决什么问题? ⭐)
- [#7 SavedStateHandle 是什么? ⭐](#7 SavedStateHandle 是什么? ⭐)
- [进阶层(7 题)](#进阶层(7 题))
-
- [#8 ViewModel 如何在配置变更后保持数据?底层机制是什么? 🔥](#8 ViewModel 如何在配置变更后保持数据?底层机制是什么? 🔥)
- [#9 LiveData 的「粘性」是什么意思?有什么坑? 🔥](#9 LiveData 的「粘性」是什么意思?有什么坑? 🔥)
- [#10 LiveData 和 StateFlow 怎么选? 🔥](#10 LiveData 和 StateFlow 怎么选? 🔥)
- [#11 Lifecycle-aware 组件有哪些?原理是什么? ⭐](#11 Lifecycle-aware 组件有哪些?原理是什么? ⭐)
- [#12 Room 的基本架构是什么? ⭐](#12 Room 的基本架构是什么? ⭐)
- [#13 WorkManager 和 Foreground Service 怎么选? 💡](#13 WorkManager 和 Foreground Service 怎么选? 💡)
- [#14 DataStore 和 SharedPreferences 有什么区别? ⭐](#14 DataStore 和 SharedPreferences 有什么区别? ⭐)
- [核心层(6 题)](#核心层(6 题))
-
- [#15 ViewModel + Repository 模式怎么设计? 🔥](#15 ViewModel + Repository 模式怎么设计? 🔥)
- [#16 Hilt 依赖注入的基本原理是什么? ⭐](#16 Hilt 依赖注入的基本原理是什么? ⭐)
- [#17 进程死亡后 ViewModel 数据还在吗?如何恢复? 💡](#17 进程死亡后 ViewModel 数据还在吗?如何恢复? 💡)
- [#18 Navigation 深链(Deep Link)与安全注意什么? 💡](#18 Navigation 深链(Deep Link)与安全注意什么? 💡)
- [#19 LiveData 的 map 和 switchMap 有什么区别? 💡](#19 LiveData 的 map 和 switchMap 有什么区别? 💡)
- [#20 Jetpack 组件如何与 Kotlin 协程整合? 🔥](#20 Jetpack 组件如何与 Kotlin 协程整合? 🔥)
- 面试策略速查
- 完整链路一句通
- 相关推荐
学习建议
| 目标层级 | 建议 |
|---|---|
| 初级 | 掌握基础层 7 题:Lifecycle 状态、ViewModel 作用、LiveData 特性、Navigation 基本用法;工程联想看追问第 1 条 |
| 中级 | 通读全文;进阶层能讲清 LiveData 粘性、StateFlow 对比、Room 架构、DataStore 选型 |
| 高级 | 核心层必答:ViewModel+Repository、进程死亡恢复、Hilt 注入边界、Jetpack 与协程整合;能串联「Lifecycle→ViewModel→数据层→UI」完整链路 |
基础层(7 题)
#1 Jetpack 是什么?包含哪些核心组件? ⭐
标准回答
Jetpack 是 Google 官方 Android 架构组件库集合,解决生命周期、数据持久化、后台任务、导航等共性问题。核心包括 Lifecycle、ViewModel、LiveData/Flow、Room、Navigation、WorkManager、DataStore、Hilt 等;按功能分架构、UI、行为、基础四类,统一 Kotlin 优先 API。
面试官可能继续追问
-
Android 工程里 Jetpack 怎么落地?
新模块用 ViewModel + Room + Navigation + Hilt;旧代码逐步替换 AsyncTask/SharedPreferences,不一次性全量迁移。
-
Jetpack 和 Support Library 什么关系?
Support Library 已废弃,功能由 AndroidX/Jetpack 承接,包名
androidx.*,与 Support 不兼容混用。
#2 Lifecycle 是什么?LifecycleOwner 和 LifecycleObserver 怎么协作? 🔥
标准回答
Lifecycle 将组件(Activity/Fragment)生命周期抽象为 CREATED→STARTED→RESUMED→DESTROYED 状态机;LifecycleOwner 持有 Lifecycle,LifecycleObserver 通过 @OnLifecycleEvent 或 DefaultLifecycleObserver 在状态变化时收回调,避免在错误生命周期操作资源。
面试官可能继续追问
-
Android 里 Lifecycle 典型用法?
lifecycleScope绑定协程、LiveData.observe自动解绑、自定义相机/定位模块实现LifecycleObserver在ON_STOP释放。 -
STARTED和RESUMED对后台任务意味着什么?STARTED可见但可能未获焦点;RESUMED可交互。定位/传感器常在STARTED启、STOPPED停。
#3 ViewModel 的作用是什么?为什么能跨配置变更存活? 🔥
标准回答
ViewModel 存放 UI 相关数据与业务逻辑,配置变更(旋转屏)时实例由 ViewModelStore 保留,新 Activity/Fragment 通过同一 ViewModelStoreOwner 取回。它不应持有 Activity/View 引用,生命周期长于 UI 但短于进程;onCleared() 时清理资源。
面试官可能继续追问
-
Android 里 ViewModel 怎么创建?
by viewModels()或 Hilt@HiltViewModel;Fragment 间共享用activityViewModels()。 -
ViewModel 和 onSaveInstanceState 分工?
ViewModel 存可重建的业务状态;
SavedStateHandle/Bundle 存轻量 UI 状态与进程被杀后的恢复数据。
#4 LiveData 是什么?有什么特点? ⭐
标准回答
LiveData 是可观察的数据持有者,生命周期感知:仅在 STARTED 及以上活跃观察者收到更新;主线程分发,支持 map/switchMap/MediatorLiveData 组合。默认粘性:新观察者立即收到最新值。
面试官可能继续追问
-
Android 里 LiveData 典型场景?
ViewModel 暴露
LiveData<UiState>,Activityobserve(viewLifecycleOwner)刷新 UI;RoomLiveData查询自动刷新列表。 -
LiveData 能在后台线程 post 吗?
postValue可子线程更新,内部切主线程分发;setValue须主线程。
#5 LiveData 和 RxJava Observable 有什么区别? 🔥
标准回答
生命周期 :LiveData 自动随 Owner 解绑,Observable 需手动 dispose;线程 :LiveData 主线程分发,Rx 可任意调度;背压:LiveData 无背压,只保留最新值;Rx 操作符丰富。现代 Kotlin 项目更倾向 Flow/StateFlow 替代二者。
面试官可能继续追问
-
Android 项目里还要引入 RxJava 吗?
存量 Rx 可保留;新功能优先协程+Flow,减少依赖与生命周期泄漏风险。
-
LiveData 能组合多个数据源吗?
MediatorLiveData合并多源;复杂流式逻辑用 Flowcombine/flatMapLatest更清晰。
#6 Navigation 组件解决什么问题? ⭐
标准回答
Navigation 统一管理 Fragment 目的地、跳转参数与返回栈,用 NavGraph XML/Kotlin DSL 声明路由,NavController 执行 navigate/popBackStack。支持 Safe Args 类型安全传参、Deep Link、单一 Activity 多 Fragment 架构。
面试官可能继续追问
-
Android 里 Navigation 怎么传参?
Safe Args 生成 Directions 类;复杂对象用
@Parcelize或共享 ViewModel,避免大对象放 Bundle。 -
多模块怎么拆 NavGraph?
include子图或动态NavInflater;feature 模块暴露 destination id 与 action。
#7 SavedStateHandle 是什么? ⭐
标准回答
SavedStateHandle 是 ViewModel 构造参数,提供键值存取并在进程被杀后通过 SavedStateRegistry 自动恢复。适合导航参数、表单草稿等需在死亡后重建的轻量状态;大数据仍应走 Repository/数据库。
面试官可能继续追问
-
Android 里 SavedStateHandle 怎么用?
Hilt ViewModel 注入
SavedStateHandle,getLiveData("key")或getStateFlow绑定 UI;进程恢复后自动回填。 -
和
onSaveInstanceState区别?SavedStateHandle 在 ViewModel 层声明式存取;Bundle 更偏 View 层瞬时状态,职责应分离。
进阶层(7 题)
#8 ViewModel 如何在配置变更后保持数据?底层机制是什么? 🔥
标准回答
Activity retainNonConfig 机制由 ActivityThread 在销毁非配置变更时把 ViewModelStore 交给新实例。ViewModelProvider 以 Class+Key 从 Store 取缓存;非配置变更不调用 onCleared(),配置变更重建 UI 后复用同一 ViewModel 实例。
面试官可能继续追问
-
Android 里如何验证 ViewModel 存活?
旋转屏幕后观察
ViewModel内计数器/请求任务是否中断;LoghashCode应一致。 -
Fragment 的 ViewModelStore 作用域?
默认 Fragment 私有;
requireActivity()共享 Activity 级 Store,多 Fragment 共享数据用activityViewModels()。
#9 LiveData 的「粘性」是什么意思?有什么坑? 🔥
标准回答
粘性指新 observe 的观察者立即收到 LiveData 当前缓存的最新值,即使用户未触发新事件。适合展示最新 UI 状态,但一次性事件(Toast、导航)会被重复消费,需 SingleLiveEvent 或改 StateFlow/Channel。
面试官可能继续追问
-
Android 里怎么避免粘性重复弹 Toast?
事件用
SharedFlow/Channel;或SingleLiveEvent包装,消费后清空(注意多观察者仍有问题)。 -
observeForever和observe区别?observeForever无生命周期自动移除,必须手动removeObserver,易泄漏。
#10 LiveData 和 StateFlow 怎么选? 🔥
标准回答
StateFlow :Kotlin 协程原生、冷/热流语义清晰、支持 combine/背压策略、必有初始值、非粘性重复收集可控;LiveData:Java 友好、自动生命周期绑定、主线程简单。新项目 Kotlin 优先 StateFlow;存量 LiveData+Room 可渐进迁移。
面试官可能继续追问
-
Android 里 StateFlow 怎么驱动 Compose?
collectAsStateWithLifecycle()收集;ViewModelstateIn/SharingStarted.WhileSubscribed控制上游生命周期。 -
Room 返回 Flow 还是 LiveData?
新代码用
Flow+协程;LiveData查询仍支持但 Flow 更灵活,便于操作符组合。
#11 Lifecycle-aware 组件有哪些?原理是什么? ⭐
标准回答
LiveData、LifecycleObserver、DefaultLifecycleObserver、LifecycleService、ProcessLifecycleOwner 等均为生命周期感知。核心是在 Lifecycle 状态变化时注册/注销回调或启停任务,避免在 DESTROYED 后访问 UI 或泄漏观察者。
面试官可能继续追问
-
Android 里
ProcessLifecycleOwner用途?感知 App 前后台切换,统一暂停定位、刷新令牌、埋点会话;不等同于单个 Activity 生命周期。
-
自定义组件怎么接入 Lifecycle?
实现
LifecycleObserver或用lifecycle.addObserver,在ON_DESTROY释放资源。
#12 Room 的基本架构是什么? ⭐
标准回答
Room 是 SQLite 抽象层:@Entity 定义表、@Dao 声明查询(支持 suspend/Flow/LiveData)、@Database 聚合并提供实例。编译期生成实现,运行时通过 RoomDatabase 管理连接池与迁移;与 Flow/协程深度整合,主线程查询默认禁止。
面试官可能继续追问
-
Android 里 Room 迁移怎么做?
Migration(start, end) { db.execSQL(...) }注册到 Builder;破坏性变更用fallbackToDestructiveMigration仅开发期。 -
Room 和 SQLDelight 怎么选?
Room Jetpack 生态好、LiveData/Flow 原生;SQLDelight 类型安全 SQL、KMP 友好,跨平台选后者。
#13 WorkManager 和 Foreground Service 怎么选? 💡
标准回答
WorkManager :可延迟、需保证执行、受 Doze/省电约束的后台任务(同步、上传),支持约束条件与链式任务;Foreground Service:用户可感知的长时间运行(导航、音乐、通话),须通知且受 Android 12+ 前台服务类型限制。即时用户可见用 FGS;可延后且可重试用 WorkManager。
面试官可能继续追问
-
Android 里周期性同步用什么?
PeriodicWorkRequest最小间隔约 15 分钟;更精确闹钟用AlarmManager+合规豁免,注意省电策略。 -
WorkManager 能保证实时吗?
不能;系统按约束调度,实时任务不适合 WorkManager。
#14 DataStore 和 SharedPreferences 有什么区别? ⭐
标准回答
DataStore (Preferences/Proto):异步 API、基于协程/Flow、类型安全(Proto)、事务一致性更好;SharedPreferences :同步 commit/apply、主线程 ANR 风险、无结构校验。新配置存储优先 DataStore;Proto DataStore 适合结构化配置。
面试官可能继续追问
-
Android 里 DataStore 迁移 SP 注意什么?
单进程读写、用
dataStore委托单例;迁移期可用SharedPreferencesMigration一次性导入旧数据。 -
多进程能共享 DataStore 吗?
不支持;多进程仍须 ContentProvider 或各自存储+同步策略。
核心层(6 题)
#15 ViewModel + Repository 模式怎么设计? 🔥
标准回答
ViewModel 暴露 UI 状态(StateFlow/LiveData),调用 Repository 获取数据;Repository 统一本地(Room)与远程(Retrofit)数据源,屏蔽缓存策略与错误转换。ViewModel 不直接访问网络/数据库,便于测试与生命周期管理;单向数据流:事件上行、状态下发。
面试官可能继续追问
-
Android 里 Repository 缓存策略怎么定?
先返本地 Flow 再网络刷新(NetworkBoundResource 思路);离线优先用 Room,在线用
remoteMediator(Paging 3)。 -
ViewModel 能持有 Repository 吗?
可以,通过 Hilt 注入单例 Repository;避免在 ViewModel 内 new 数据源导致重复连接。
#16 Hilt 依赖注入的基本原理是什么? ⭐
标准回答
Hilt 基于 Dagger,编译期生成组件树:@HiltAndroidApp Application 根、@AndroidEntryPoint 注入 Activity/Fragment、@HiltViewModel 注入 ViewModel。@Module+@Provides/@Binds 声明绑定,@Singleton 等 Scope 控制生命周期;减少手动工厂与 Service Locator 反模式。
面试官可能继续追问
-
Android 里 Hilt 模块怎么拆?
DatabaseModule、NetworkModule、RepositoryModule分文件;feature 模块用@InstallIn(SingletonComponent::class)。 -
Hilt 和 Koin 怎么选?
Hilt 编译期安全、Google 官方;Koin 运行时轻量、学习曲线低,大型工程倾向 Hilt。
#17 进程死亡后 ViewModel 数据还在吗?如何恢复? 💡
标准回答
进程被系统回收后 ViewModelStore 清空,ViewModel 数据丢失。恢复靠 SavedStateHandle、持久化(Room/DataStore)或重新拉取远程。ViewModel 适合配置变更存活,不适合替代持久化;用户输入草稿应写 SavedStateHandle 或本地库。
面试官可能继续追问
-
Android 里如何测试进程死亡恢复?
开发者选项「不保留活动」或
adb shell am kill;验证 SavedStateHandle/Room 是否回填。 -
为什么旋转屏不丢数据但杀进程会丢?
前者同一进程内 ViewModelStore 保留;后者进程内存整体回收。
#18 Navigation 深链(Deep Link)与安全注意什么? 💡
标准回答
Deep Link 通过 Intent URI 或 App Links 导航到指定 destination;须在 Manifest/NavGraph 声明 deepLink,验证参数防注入。App Links 需 assetlinks.json 域名验证;敏感操作(支付、删数据)深链入口须二次鉴权,不可仅凭 URI 参数信任。
面试官可能继续追问
-
Android 里 App Links 和 Deep Link 区别?
App Links 验证域名后默认打开 App 无选择器;普通 Deep Link 可能弹出应用选择框。
-
NavGraph 深链参数怎么校验?
Safe Args 类型约束+ViewModel 内业务校验;拒绝非法 id 与越权路由。
#19 LiveData 的 map 和 switchMap 有什么区别? 💡
标准回答
map 一对一转换每个值;switchMap 将每个源值映射为新的 LiveData 并只观察最新 inner LiveData,源变化时自动切换订阅、取消旧源。搜索框联想、用户切换触发新请求等「随输入换数据源」场景用 switchMap。
面试官可能继续追问
-
Android 里搜索防抖怎么实现?
Flow 侧
debounce+flatMapLatest更自然;LiveData 需switchMap+延迟或 MediatorLiveData 手动防抖。 -
对应 Flow 操作符是什么?
map对应map;switchMap对应flatMapLatest。
#20 Jetpack 组件如何与 Kotlin 协程整合? 🔥
标准回答
lifecycleScope/viewModelScope 管理协程生命周期;Room/Retrofit 提供 suspend API;ViewModel 用 StateFlow+stateIn 暴露状态;repeatOnLifecycle/flowWithLifecycle 安全收集 Flow。WorkManager CoroutineWorker、DataStore 全异步 API,形成「Scope→挂起→Flow→UI」统一异步模型。
面试官可能继续追问
-
Android 里
repeatOnLifecycle解决什么问题?仅在
STARTED以上收集 Flow,避免后台无效收集与泄漏;替代launchWhenStarted挂起语义。 -
viewModelScope默认 Dispatcher 是什么?Dispatchers.Main.immediate+SupervisorJob;IO 操作用withContext(Dispatchers.IO)。
面试策略速查
| 面试等级 | 建议掌握 |
|---|---|
| 初级 | ★★★☆☆ |
| 中级 | ★★★★☆ |
| 高级 | ★★★★★ |
必背知识(🔥)
Lifecycle 状态机、ViewModel 跨配置变更、LiveData 粘性与生命周期感知、LiveData vs StateFlow、ViewModel+Repository、Jetpack 协程整合(lifecycleScope/viewModelScope/repeatOnLifecycle)
高频追问
「旋转屏数据为什么不丢」「LiveData 粘性导致 Toast 重复」「StateFlow 和 LiveData 选型」「进程死了 ViewModel 还在吗」「SavedStateHandle 和 ViewModel 分工」
加分项(💡)
WorkManager vs FGS 选型、Deep Link 安全、map/switchMap 与 flatMapLatest 对应、进程死亡恢复测试
容易踩坑
用 ViewModel 当持久化;LiveData 一次性事件不处理粘性;observeForever 不 remove;主线程读 SharedPreferences;Navigation 大对象塞 Bundle
完整链路一句通
Jetpack 核心一条线:Lifecycle 约束组件存活边界 → ViewModel 在 Store 内跨配置变更持有 UI 状态 → Repository 统一数据源 → LiveData/StateFlow 下发状态、协程 Scope 管理异步 → Navigation 管路由 → Room/DataStore 持久化;进程死亡靠 SavedStateHandle 与本地库恢复,而非指望 ViewModel 常驻。