Android 高级工程师面试:Jetpack 核心 近1年高频追问 20 题

文章目录

学习建议

目标层级 建议
初级 掌握基础层 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 持有 LifecycleLifecycleObserver 通过 @OnLifecycleEventDefaultLifecycleObserver 在状态变化时收回调,避免在错误生命周期操作资源。

面试官可能继续追问

  • Android 里 Lifecycle 典型用法?

    lifecycleScope 绑定协程、LiveData.observe 自动解绑、自定义相机/定位模块实现 LifecycleObserverON_STOP 释放。

  • STARTEDRESUMED 对后台任务意味着什么?

    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>,Activity observe(viewLifecycleOwner) 刷新 UI;Room LiveData 查询自动刷新列表。

  • 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 合并多源;复杂流式逻辑用 Flow combine/flatMapLatest 更清晰。


标准回答

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 注入 SavedStateHandlegetLiveData("key")getStateFlow 绑定 UI;进程恢复后自动回填。

  • onSaveInstanceState 区别?

    SavedStateHandle 在 ViewModel 层声明式存取;Bundle 更偏 View 层瞬时状态,职责应分离。


进阶层(7 题)

#8 ViewModel 如何在配置变更后保持数据?底层机制是什么? 🔥

标准回答

Activity retainNonConfig 机制由 ActivityThread 在销毁非配置变更时把 ViewModelStore 交给新实例。ViewModelProviderClass+Key 从 Store 取缓存;非配置变更不调用 onCleared(),配置变更重建 UI 后复用同一 ViewModel 实例。

面试官可能继续追问

  • Android 里如何验证 ViewModel 存活?

    旋转屏幕后观察 ViewModel 内计数器/请求任务是否中断;Log hashCode 应一致。

  • Fragment 的 ViewModelStore 作用域?

    默认 Fragment 私有;requireActivity() 共享 Activity 级 Store,多 Fragment 共享数据用 activityViewModels()


#9 LiveData 的「粘性」是什么意思?有什么坑? 🔥

标准回答

粘性指新 observe 的观察者立即收到 LiveData 当前缓存的最新值,即使用户未触发新事件。适合展示最新 UI 状态,但一次性事件(Toast、导航)会被重复消费,需 SingleLiveEvent 或改 StateFlow/Channel。

面试官可能继续追问

  • Android 里怎么避免粘性重复弹 Toast?

    事件用 SharedFlow/Channel;或 SingleLiveEvent 包装,消费后清空(注意多观察者仍有问题)。

  • observeForeverobserve 区别?

    observeForever 无生命周期自动移除,必须手动 removeObserver,易泄漏。


#10 LiveData 和 StateFlow 怎么选? 🔥

标准回答

StateFlow :Kotlin 协程原生、冷/热流语义清晰、支持 combine/背压策略、必有初始值、非粘性重复收集可控;LiveData:Java 友好、自动生命周期绑定、主线程简单。新项目 Kotlin 优先 StateFlow;存量 LiveData+Room 可渐进迁移。

面试官可能继续追问

  • Android 里 StateFlow 怎么驱动 Compose?

    collectAsStateWithLifecycle() 收集;ViewModel stateIn/SharingStarted.WhileSubscribed 控制上游生命周期。

  • Room 返回 Flow 还是 LiveData?

    新代码用 Flow+协程;LiveData 查询仍支持但 Flow 更灵活,便于操作符组合。


#11 Lifecycle-aware 组件有哪些?原理是什么? ⭐

标准回答

LiveData、LifecycleObserver、DefaultLifecycleObserverLifecycleServiceProcessLifecycleOwner 等均为生命周期感知。核心是在 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 模块怎么拆?

    DatabaseModuleNetworkModuleRepositoryModule 分文件;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 保留;后者进程内存整体回收。


标准回答

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 对应 mapswitchMap 对应 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 常驻。


相关推荐

Android 高级工程师面试:Kotlin 语法基础 近1年高频追问 22 题

Android 高级工程师面试:Java 基础知识 近1年高频追问 22 题

相关推荐
爱笑鱼2 小时前
Handler(四):Handler 卡顿怎么定位?从 Slow delivery 到 Slow dispatch
android
九皇叔叔2 小时前
RHEL9.8 配置本地镜像仓库
android·java·缓存
私人珍藏库3 小时前
[Android] 聊天记录微备份 -聊天记录备份+本地数据备份
android·人工智能·app·软件·多功能
私人珍藏库4 小时前
[Android] PocketPal -本地离线AI助手+大模型部署神器
android·人工智能·app·软件·多功能
折哥的程序人生 · 物流技术专研4 小时前
第8篇:模板方法模式的优缺点与面试高频考点
java·设计模式·面试·模板方法模式·行为型模式·优缺点·扩充系列
listening7774 小时前
HarmonyOS 6.1 跨端实战:用ArkUI-X把电商App同时跑在Android/iOS上
android·ios·harmonyos
爱笑鱼4 小时前
Handler(三):主线程、HandlerThread、Binder 线程到底怎么区分?
android
w139548564224 小时前
鸿蒙实战:报告与雷达图 ReportDao
android·华为·harmonyos·鸿蒙系统
爱笑鱼5 小时前
Handler(二):MessageQueue 为什么不是普通队列?
android