1、ViewModel 作用
答案
管理页面业务数据、处理业务逻辑;生命周期独立于 Activity/Fragment ,屏幕旋转、配置变更数据不丢失;
配合viewModelScope管理协程,自动取消防泄漏;
还可实现多 Fragment 共享通信。
2、ViewModel 生命周期特点
答案
配置变更(旋转屏幕、切语言)不销毁;
只有页面真正 finish / 彻底销毁时,ViewModel 才会销毁。
3、为什么屏幕旋转 ViewModel 数据不会丢?
答案
ViewModel 存在 ViewModelStore,不和临时重建的 Activity 绑定;
新 Activity 重建后复用同一个 ViewModel 实例,数据保留。
4、ViewModel 能不能持有 Activity 引用?为什么?
答案
不能。
ViewModel 生命周期比 Activity 长,强引用会造成内存泄漏;
只能使用 Application Context,不能用 Activity 上下文、View 引用。
5、viewModelScope 是什么?作用
答案
ViewModel 自带协程作用域;
绑定 ViewModel 生命周期,ViewModel 销毁时自动取消所有协程,杜绝协程泄漏,不用手动 cancel。
6、ViewModel 会不会内存泄漏?什么情况会泄漏
答案 本身设计防泄漏,人为写错才会漏:
- 持有 Activity/View 强引用
- 内部用 GlobalScope 协程
- 静态持有 ViewModel 实例
- 网络 / 异步回调持有页面引用
7、ViewModel 与 SavedStateHandle 作用
答案
ViewModel 只能保配置变更数据;
系统杀进程、后台重建数据会丢;
SavedStateHandle 可轻量保存简单数据,进程被杀重建也能恢复。
8、多个 Fragment 怎么通信?
答案
共享同一个 ViewModel,通过 LiveData/Flow 收发数据,解耦不用接口回调。
9、ViewModel 和 onSaveInstanceState 区别
答案
ViewModel:存复杂业务数据、列表对象,配置变更不丢;进程被杀不保 。onSaveInstanceState:只存少量基础类型,进程被杀也能恢复,容量小。
10、ViewModel 为什么不建议放 UI 控件?
答案
违背分离架构;ViewModel 不该持有 View 引用,容易内存泄漏、耦合 UI 层。
面试口述极简总结
ViewModel 用于托管页面数据和业务逻辑,生命周期独立于 View,配置变更数据不重建;不持有 Activity 和 View 引用避免内存泄漏;自带 viewModelScope 自动管理协程生命周期;多 Fragment 可共享通信,搭配 SavedStateHandle 还能处理系统杀进程数据恢复。
11、Fragment的ViewModel如何访问到Activity的ViewModel的数据
1、核心一句话
Fragment 和 Activity 共享同一个 ViewModel 实例 ,Fragment 用所属 Activity 的作用域获取 ViewModel,就能直接拿到 Activity 里的数据。
2、具体原理
- ViewModel 是按 ViewModelStoreOwner 来隔离实例的;
- 如果 Fragment 获取 ViewModel 时,指定
requireActivity()作为所有者,就会复用 Activity 级别的同一个 ViewModel; - 同一个实例里的数据、LiveData、状态,Fragment 直接可读可观察。
3、Activity 里创建
kotlin
csharp
val activityVm: MainViewModel by viewModels()
4、Fragment 里获取(关键)
kotlin
csharp
val activityVm: MainViewModel by activityViewModels()
activityViewModels() 本质就是以 宿主 Activity 为 ViewModel 持有者,拿到同一份实例。
Fragment 想要访问 Activity 的 ViewModel 数据,直接用 activityViewModels() 方式获取,会以宿主 Activity 为生命周期所有者,拿到和 Activity 同一个 ViewModel 实例,从而共享里面所有数据和 LiveData,实现 Fragment 与 Activity、Fragment 与 Fragment 解耦通信。
12、多个Fragement怎么共享一个ViewModel的数据?
核心原理
多个 Fragment 共用宿主 Activity 作为 ViewModel 持有者,拿同一个 ViewModel 实例,就能共享数据。
两种实现方式
方式一:用 activityViewModels ()(最简单)
每个 Fragment 里都这样写:
kotlin
csharp
val sharedVm: HomeViewModel by activityViewModels()
- 所有 Fragment 拿到同一个 ViewModel 对象
- 读写同一个变量、观察同一个 LiveData,自动共享数据
方式二:手动指定宿主 Activity
kotlin
scss
val vm = ViewModelProvider(requireActivity())[HomeViewModel::class.java]
效果和 activityViewModels() 完全一样。
为什么能共享
- ViewModel 是按 ViewModelStoreOwner 隔离实例;
- 都以 宿主 Activity 为 Owner,就会拿到同一份 ViewModel;
- 同一份实例里的变量、LiveData、状态全部互通。
面试一句话口述
多个 Fragment 通过 activityViewModels 方式获取 ViewModel,统一以宿主 Activity 为生命周期持有者,拿到同一个 ViewModel 实例,通过内部 LiveData 实现数据共享和跨 Fragment 通信,解耦且不会内存泄漏。