ViewModel

发布于:2024-12-18 ⋅ 阅读:(32) ⋅ 点赞:(0)

ViewMode是MVVM架构模式中VM层对应的类,它的作用是存储界面数据,并和界面发生数据交互。ViewModel能感知生命周期,并且在界面由于配置问题发生重建时候,可以保持当前的数据不变。生命周期如下:
在这里插入图片描述

ViewMode由ViewModeProvider创建,然后把创建的ViewModel放入ViewModelStore内部。
MainActivity:

val viewModel : CalendarViewModel by lazy {
        ViewModelProvider(this, ViewModelProvider.NewInstanceFactory())
            .get(CalendarViewModel::class.java)
    }
    

ViewModelProvider:

public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
        return try {
            factory.create(modelClass, extras) //创建viewModel
        } catch (e: AbstractMethodError) {
            factory.create(modelClass)
        }.also { store.put(key, it) }  //把ViewModel放入Store的hashmap中
    }

当配置改变导致的重建时,ViewModelStore不会被重建或者清除,因此ViewModel也不会重建,这主要是因为viewModelStore是被存在ActivityClientRecord中,Activity的销毁不会影响它。
从源代码看看:
Activity被修改配置后(如屏幕旋转)后,导致的销毁重建,会调用onRetainNonConfigurationInstance这个函数,viewModelStore就是在这里恢复的:

  final override fun onRetainNonConfigurationInstance(): Any? {
        var viewModelStore = _viewModelStore
        if (viewModelStore == null) {
            // ViewModelStore from our last NonConfigurationInstance
            val nc = lastNonConfigurationInstance as NonConfigurationInstances?
            if (nc != null) {
                viewModelStore = nc.viewModelStore
            }
        }
    }

这里还要获取到上一次的非配置实例lastNonConfigurationInstance,它就是通过ActivityThread中的attach方法,传递给Activity内部的:

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	activity.attach(...,r.lastNonConfigurationInstances,...);
}

所以从最后看出,viewModel的数据实际是保存在ActivityClientRecord中的。

ViewModel感知生命周期,是通过Lifecycle去实现的,如下:

lifecycle.addObserver(
            LifecycleEventObserver { _, event ->
                if (event == Lifecycle.Event.ON_DESTROY) {     
                    if (!isChangingConfigurations) { //不是配置改变,才会清除viewmodelStore
                        viewModelStore.clear()
                    }
                }
            }
        )

这里也可以看到,当正常的界面销毁(非配置改变导致的销毁)会调用到ViewModelStore的clear方法,清除ViewModel的数据。


网站公告

今日签到

点亮在社区的每一天
去签到