Jetpack之ViewModel源码分析

233 阅读1分钟

一、最官方的使用方法,不多BB直接上链接

DataBinding使用简介:  戳我👉

二、源码分析

  1. 简单使用
class ViewModelActivity : AppCompatActivity(){
    private val viewModel: TestViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewModel.name.observe(this){
            Toast.makeText(this,"this is $it", Toast.LENGTH_LONG).show()
        }
    }

    override fun onRetainCustomNonConfigurationInstance(): Any? {
        Log.e("SKY","onRetainCustomNonConfigurationInstance")
        return super.onRetainCustomNonConfigurationInstance()
    }

    override fun getLastNonConfigurationInstance(): Any? {
        Log.e("SKY","getLastNonConfigurationInstance")
        return super.getLastNonConfigurationInstance()
    }
}

首先,介绍两个方法 onRetainCustomNonConfigurationInstance() 当配置发生变化的时候保存一些信息。也就是发送旋转时,可以在这里保存一些信息;getLastNonConfigurationInstance() 这个是获取最后一次保存的信息 接下来我们来看看源码

  1. 首次初始化 我们打开ViewModelActivity时,就是进行初始化我们的viewmodel,通过by ViewModels()来初始化,我们看viewModels()做了什么,它 return ViewModelLazy()
inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
    noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
    val factoryPromise = factoryProducer ?: {
        defaultViewModelProviderFactory
    }

    return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
}

接着看 ViewModelLazy()做了什么,这里通过ViewModelProvider调用get()方法

image.png

点进get(),依然是调用get(),这次是将一个字符串+获取我们ViewModel的类的名称和ViewModel的class传进去

public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {
    String canonicalName = modelClass.getCanonicalName();
    if (canonicalName == null) {
        throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");
    }
    return get(DEFAULT_KEY + ":" + canonicalName, modelClass);
}

继续点击get()看

image.png

简单说一下mViewModelStore,这就是一个map,就是存放ViewModel的

private final HashMap<String, ViewModel> mMap = new HashMap<>();

这就是首次进来的时候初始化ViewModel

  1. 当屏幕发送旋转
    1. AndroidManifest.xml中相关activity设置android:configChanges="orientation|keyboardHidden|screenSize"时,生命周期不发生变化,只是回调onConfigurationChanged()
    2. 当没有1配置时,就会重新走activity的生命周期 onPause --> onStop --> onDestroy --> onCreate --> onStart --> onResume

首先同样也是会走之前的 “首次初始化”流程,只是在第二个get方法中,也就是有绿色文字标注的地方返回了我们之前保存的ViewModel,就可以记录上次的ViewModel中的值了

  1. 数据是怎么保存的呢 在开始的时候我们介绍了两个方法,当屏幕旋转的时候回调用 onRetainCustomNonConfigurationInstance() 来保存数据,

image.png

那么我们看看这个 onRetainNonConfigurationInstance() 是在哪调用的呢

image.png

三、END~