Jetpack ViewModel源码分析
·
文章目录
Jetpack ViewModel源码分析
概述
ViewModel 是一种可以感知生命周期的来存储和管理的与 UI 相关的数据。能在屏幕旋转、预言切换等配置变更时保存数据,避免数据丢失和重复加载。
核心类
-
ViewModel:抽象类
- 用于管理与UI相关的数据。
-
ViewModelStore:类
- 用于存储 ViewModel 的容器。
- 内部是
HashMap <String, ViewModel>的数据结构,键是 ViewModel 的类名,值是 ViewModel 实例。 - 每个 Activity/Fragment 内部都持有一个 ViewModelStore 实例。
-
ViewModelStoreOwner:接口
- Activity/Fragment 是其实现类。
- 用于定义获取 ViewModelStore 的规范,指明 ViewModel 的作用域,是和哪个 Activity/Fragment 绑定。
-
ViewModelProvider:类
- 用于获取 ViewModel 实例。
- 会检查 ViewModelStore 是否缓存,如果有缓存则直接返回实例,如果没有缓存则通过 Factory 创建新实例,并存入 ViewModelStore。
-
ViewModel:数据管理类。
-
ViewModelProvider:用于创建管理ViewModel实例。
-
ViewModelStore:用于存储ViewModel实例。
-
ViewModelStoreOwner:是一个接口,用于获取ViewModelStore实例。
-
Activity$NonConfigurationInstances:用于配置变更情况下缓存数据。
生命周期图

流程
- 获取 ViewModel:首次调用
ViewModelProvider(this).get(MyViewModel::class.java)时,ViewModeProvider 会尝试从 Activity 的 ViewModelStore 中获取 ViewModel 实例。 - 创建和存储 ViewModel:如果 ViewModelStore 中没有该实例,则通过 ViewModelProvider 创建实例;如果存在实例,则直接返回。
- 配置发生变更:当屏幕旋转时,系统会先销毁再重建 Activity,
- 被销毁前,会调用 onRetainNonConfigurationInstance() ,系统会缓存 Activity 的ViewModelStore 对象。
- 重建后,新 Activity 被创建, ViewModelProvider 通过保留下来的 ViewModelStore 获取 ViewModel 实例。
源码分析
创建阶段
ViewModelProvider类基本属性
public open class ViewModelProvider @JvmOverloads constructor(
private val store: ViewModelStore,
private val factory: Factory,
private val defaultCreationExtras: CreationExtras = CreationExtras.Empty,
) {
public constructor(
owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))
public constructor(owner: ViewModelStoreOwner, factory: Factory) : this(
owner.viewModelStore,
factory,
defaultCreationExtras(owner)
)
public interface Factory {
public fun <T : ViewModel> create(modelClass: Class<T>): T {
throw UnsupportedOperationException(
"Factory.create(String) is unsupported. This Factory requires " +
"`CreationExtras` to be passed into `create` method."
)
}
}
}
ViewModelProvider#get()
public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
// 获取ViewModel类的完整类名
val canonicalName = modelClass.canonicalName
?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels")
// 使用类名作为key值
return get("$DEFAULT_KEY:$canonicalName", modelClass)
}
@MainThread
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
// 先从ViewModelStore中获取ViewModel实例
val viewModel = store[key]
if (modelClass.isInstance(viewModel)) {
// 如果ViewModel实例存在,则直接返回
(factory as? OnRequeryFactory)?.onRequery(viewModel!!)
return viewModel as T
} else {
// ViewModel实例的类型不匹配
if (viewModel != null) {
// TODO: log a warning.
}
}
val extras = MutableCreationExtras(defaultCreationExtras)
extras[VIEW_MODEL_KEY] = key
// 通过Factory创建ViewModel实例
return try {
factory.create(modelClass, extras)
} catch (e: AbstractMethodError) {
factory.create(modelClass)
}.also {
// 将新创建的ViewModel实例存入ViewModelStore中
store.put(key, it)
}
}
保存阶段
ComponentActivity#onRetainNonConfigurationInstance()
// 配置变更时会销毁Activity,销毁前会回调该方法
final override fun onRetainNonConfigurationInstance(): Any? {
// Maintain backward compatibility.
val custom = onRetainCustomNonConfigurationInstance()
// 获取当前的ViewModelStore
var viewModelStore = _viewModelStore
if (viewModelStore == null) {
val nc = lastNonConfigurationInstance as NonConfigurationInstances?
if (nc != null) {
viewModelStore = nc.viewModelStore
}
}
if (viewModelStore == null && custom == null) {
return null
}
// 通过NonConfigurationInstances实例缓存ViewModelStore对象
val nci = NonConfigurationInstances()
nci.custom = custom
nci.viewModelStore = viewModelStore
// 返回系统对象
return nci
}
恢复阶段
Activiy 被重建了,调用 ViewModelProvider(this) 创建新的 ViewModelProvider 实例,会调用 ComponentActivity 的 viewModelStore 访问器。
ComponentActivity.viewModelStore属性
override val viewModelStore: ViewModelStore
get() {
checkNotNull(application) {
("Your activity is not yet attached to the " +
"Application instance. You can't request ViewModel before onCreate call.")
}
ensureViewModelStore()
return _viewModelStore!!
}
ComponentActivity#ensureViewModelStore()
private fun ensureViewModelStore() {
if (_viewModelStore == null) {
val nc = lastNonConfigurationInstance as NonConfigurationInstances?
// 如果配置对象存在,则获取ViewModelStore实例
if (nc != null) {
_viewModelStore = nc.viewModelStore
}
// 如果配置对象不存在,则创建ViewModelStore实例
if (_viewModelStore == null) {
_viewModelStore = ViewModelStore()
}
}
}
总结
- 创建ViewModel阶段:通过 by viewModels() 创建 ViewModel 实例,本质是调用 ViewModelProvider(this).get(MyViewModel::class.java),会先尝试从 ViewModelStore 中获取,ViewModelStore 是一个哈希表的数据结构,如果没有则新建并缓存在 ViewModelStore,ViewModelStore 是ComponentActivity中的一个属性。
- 缓存ViewModel阶段:在配置变更情况下,ViewModelStore 会被缓存在 NonconfigurationInstances 中。
- 恢复ViewModel阶段:配置变更后会重启 Activity,会先从 NonconfigurationInstances 中读取 ViewModelStore,接着获取 ViewModel 实例。
- Activity 正常销毁时会清空 ViewModelStore。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)