美文网首页
ViewModel源码阅读笔记

ViewModel源码阅读笔记

作者: 紫鹰 | 来源:发表于2022-07-21 15:23 被阅读0次

MVVM模式实现了数据和页面的分离。ViewModel的生命周期需要跟随引用他的activity或者fragment。接下来我们就来看看,ViewModel是如何实现生命周期的伴随的。

先从ViewModel的创建开始看

XXXViewModel viewModel = new  ViewModelProvider(fragment).get(XXXViewModel.class)

kotlin扩展函数实现的方式最终也是调用ViewModelProvider的方法实现的,具体细节可以看上篇文章介绍,这里不赘述了

先看下ViewModelProvider的构造方法

public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {  
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory  
        ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()  
        : NewInstanceFactory.getInstance());  
}

构造方法需要传入一个ViewModelStoreOwner,在androidx包中的Fragment和ComponentActivity都实现了这个接口。这个稍后再看

继续看上面的代码,该构造方法调用了另一个构造方法

public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {  
    mFactory = factory;  
    mViewModelStore = store;  
}

mViewModelStore这个变量来自于ViewModelStoreOwner,接下来以Fragment为例,来看看

public ViewModelStore getViewModelStore() {  
    if (mFragmentManager == null) {  
        throw new IllegalStateException("Can't access ViewModels from detached fragment");  
    }  
    return mFragmentManager.getViewModelStore(this);  
}

这里可以看出,Fragment的ViewModelStore是保存在当前实例下。先记住这个结论,待会还用得着。

接下来看factory参数,fragment也是HasDefaultViewModelProviderFactory的实现类,因此获取factory的实例方法为

public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {  
    if (mFragmentManager == null) {  
        throw new IllegalStateException("Can't access ViewModels from detached fragment");  
    }  
    if (mDefaultFactory == null) {  
        mDefaultFactory = new SavedStateViewModelFactory(  
            requireActivity().getApplication(),  
            this,  
            getArguments());  
    }  
    return mDefaultFactory;  
}

这里的factory也是fragment中保存的实例

回到ViewModelProvider的get方法

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);  
}

最终调用的是

public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {  
    ViewModel viewModel = mViewModelStore.get(key);
    if (modelClass.isInstance(viewModel)) {  
        if (mFactory instanceof OnRequeryFactory) {  
            ((OnRequeryFactory) mFactory).onRequery(viewModel);  
        }  
        return (T) viewModel;  
    } else {  
        //noinspection StatementWithEmptyBody  
        if (viewModel != null) {  
            // TODO: log a warning.  
        }  
    }  
    if (mFactory instanceof KeyedFactory) {  
        viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);  
    } else {  
        viewModel = (mFactory).create(modelClass);  
    }  
    mViewModelStore.put(key, viewModel);  
    return (T) viewModel;  
}

这里获取缓存的viewmodel的方法 mViewModelStore.get(key)。这里的mViewModelStore就是fragment中存储的。

讲到这里,其实已经清楚了生命周期的绑定过成了。

在ViewModelProvider获取ViewModel的时候,实际上是从fragment中拿到的,如果fragment中没有的话,就创建一个,将其保存在fragment中。因此,只要拿到的fragment实例为同一个,无论新创建多少个ViewModelProvider的实例,最终获取的ViewModel都是同一个。而因为ViewModel的实例实际上是保存在fragment中,因此,viewmodel也会随fragment的销毁而销毁。

相关文章

网友评论

      本文标题:ViewModel源码阅读笔记

      本文链接:https://www.haomeiwen.com/subject/oswuirtx.html