Android架构组件—ViewModel原理

public ViewModelProvider(@NonNull ViewModelStoreOwner owner, @NonNull Factory factory) {

this(owner.getViewModelStore(), factory);

}

从ViewModelProvider的构造方法中可以看到最终是需要两个参数ViewModelStoreOwner以及Factory。这两个参数中ViewModelStoreOwner是用来存储ViewModel对象的,Factory是用来创建ViewModel对象。这个接下来的分析中也会提到。

第二步是通过ViewModelProvider的get()方法获取ViewModel实例。

public T get(@NonNull String key, @NonNull Class modelClass) {

ViewModel viewModel = mViewModelStore.get(key); // 1.是否有缓存ViewModel实例缓存

if (mFactory instanceof KeyedFactory) {

viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);

} else {

viewModel = (mFactory).create(modelClass);

}

mViewModelStore.put(key, viewModel);

return (T) viewModel;

}

在get()方法中可以看到是通过mFactory的类型来创建ViewModel的。而Factory的类型是由ViewModelStoreOwner决定的,这是ViewModelProvider的构造方法中的逻辑。其中有两种Factory,一种是SavedStateViewModelFactory,另一种是NewInstanceFactory。接下来我们直接看两种方式的区别。

SavedStateViewModelFactory创建ViewModel

public T create(@NonNull String key, @NonNull Class modelClass) {

boolean isAndroidViewModel = AndroidViewModel.class.isAssignableFrom(modelClass);

Constructor constructor;

SavedStateHandleController controller = SavedStateHandleController.create(

mSavedStateRegistry, mLifecycle, key, mDefaultArgs);

try {

T viewmodel;

if (isAndroidViewModel) {

viewmodel = constructor.newInstance(mApplication, controller.getHandle());

} else {

viewmodel = constructor.newInstance(controller.getHandle());

}

viewmodel.setTagIfAbsent(TAG_SAVED_STATE_HANDLE_CONTROLLER, controller);

return viewmodel;

}

}

在代码中可以看到,ViewModel有分为AndroidViewModel跟ViewModel,它们的区别是AndroidViewModel创建时会加入Application参数。

NewInstanceFactory创建ViewModel

public T create(@NonNull Class modelClass) {

//noinspection TryWithIdenticalCatches

try {

return modelClass.newInstance();

} catch (InstantiationException e) {

throw new RuntimeException("Cannot create an instance of " + modelClass, e);

} catch (IllegalAccessException e) {

throw new RuntimeException("Cannot create an instance of " + modelClass, e);

}

}

NewInstanceFactory创建过程相对简单,通过Class的newInstance()方法直接创建ViewModel实例。

ViewModel的销毁

这里还要分开两处说,一个是在Activity中的销毁过程,一个是在Fragment中销毁过程。

首先我们把目光放到ViewModel类来看下ViewModel销毁时都做了什么。

protected void onCleared() {}

final void clear() {

mCleared = true;

if (mBagOfTags != null) {

synchronized (mBagOfTags) {

for (Object value : mBagOfTags.values()) {

// see comment for the similar call in setTagIfAbsent

closeWithRuntimeException(value);

}

}

}

onCleared();

}

可以看到ViewModel中有clear()方法和onCleared()方法。通过跟踪方法的调用可以知道ViewModel的销毁过程。最终在ViewModelStore类中找到了clear()方法。

public final void clear() {

for (ViewModel vm : mMap.values()) {

vm.clear();

}

mMap.clear();

}

Activity中的销毁

继续跟踪代码可以看到在ComponentActivity中:

public ComponentActivity() {

getLifecycle().addObserver(new LifecycleEventObserver() {

@Override

public void onStateChanged(@NonNull LifecycleOwner source,

@NonNull Lifecycle.Event event) {

if (event == Lifecycle.Event.ON_DESTROY) {

if (!isChangingConfigurations()) {

// 销毁ViewModel

getViewModelStore().clear();

}

}

}

});

}

在ComponentActivity的构造方法中,可以看到通过Lifecycle在ON_DESTROY事件中销毁ViewModel。

Fragment中的销毁

首先通过代码跟踪到ViewModelStore的clear()方法调用的地方,在FragmentManagerViewModel类的clearNonConfigState()方法中找到了ViewModel的销毁逻辑。

void clearNonConfigState(@NonNull Fragment f) {

// Clear and remove the Fragment’s ViewModelStore

ViewModelStore viewModelStore = mViewModelStores.get(f.mWho);

if (viewModelStore != null) {

// 销毁ViewModel

viewModelStore.clear();

mViewModelStores.remove(f.mWho);

}

}

如果继续跟踪代码可以看到代码的调用栈是 FragmentStateManager::destroy() -> (Fragment状态切换)->FragmentManager::dispatchDestroy()->FragmentActivity::onDestory()。

这里有个小细节需要注意,也是我在项目中遇到的一个问题。就是ViewModel的销毁在onDestory()中,是晚于onDestoryView()的,所以要注意在使用ViewModel做操作时会不会触发组件更新。不然的话可能造成空指针异常。

ViewModel的生命周期绑定

在上面分了ViewModel的创建与销毁过程中就可以得出ViewModel生命周期是如何与组件交互的了。主要还是通过Lifecycle和组件的生命周期方法来进行回调管理。

Activity重建下的ViewModel

按照上面的逻辑,在Activity重建时会执行destory生命周期事件,那么为什么ViewModel没有销毁呢?

还是直接在代码里找答案,通过对ComponentActivity的getViewModelStore()方法进行分析。可以找到这个问题的答案。

public ViewModelStore getViewModelStore() {

if (mViewModelStore == null) {

NonConfigurationInstances nc =

(NonConfigurationInstances) getLastNonConfigurationInstance();

if (nc != null) {

// Restore the ViewModelStore from NonConfigurationInstances

mViewModelStore = nc.viewModelStore;

}

if (mViewModelStore == null) {

mViewModelStore = new ViewModelStore();

}

}

return mViewModelStore;

}

可以看大mViewModelStore变量如果是null的话,会从NonConfigurationInstances实例中取。那么我们就分析NonConfigurationInstances实例的来源。

从NonConfigurationInstances的名称可以大致判断这个类与配置无关。

public final Object onRetainNonConfigurationInstance() {

Object custom = onRetainCustomNonConfigurationInstance();

ViewModelStore viewModelStore = mViewModelStore;

if (viewModelStore == null) {

// No one called getViewModelStore(), so see if there was an existing

// ViewModelStore from our last NonConfigurationInstance

NonConfigurationInstances nc =

(NonConfigurationInstances) getLastNonConfigurationInstance();

if (nc != null) {

viewModelStore = nc.viewModelStore;

}

}

if (viewModelStore == null && custom == null) {

return null;

}

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助

因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
q-1715426094695)]

[外链图片转存中…(img-EMck3NjF-1715426094699)]

[外链图片转存中…(img-LCrQuOEp-1715426094700)]

[外链图片转存中…(img-qBHVJlks-1715426094702)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

  • 11
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Jetpack是Google提供的一套用于加速Android应用开发的工具包,其中包括了许多架构组件,其中之一就是ViewModelViewModel是一种设计模式,用于保存和管理与UI相关的数据。在传统的Android开发中,当屏幕旋转或者因为其他原因导致Activity或Fragment重建时,之前保存的临时数据就会丢失。而ViewModel的出现解决了这个问题。 ViewModel的主要作用是将数据与UI组件分离。它的工作方式是创建一个ViewModel类,并在其中保存需要与UI组件交互的数据。这样,当屏幕旋转或重建时,ViewModel实例不会销毁,数据也会得到保留。然后,在Activity或Fragment中,通过获取ViewModel实例,可以轻松地访问这些数据。 使用ViewModel的好处有很多。首先,它可以避免内存泄漏,因为ViewModel的生命周期与Activity或Fragment无关。其次,它可以节省资源,因为当Activity或Fragment销毁时,ViewModel实例可以被系统缓存起来,下次再创建时可以直接返回该实例。另外,由于ViewModel保存了与UI相关的数据,可以减少因为屏幕旋转导致的数据重复加载的问题。 在使用ViewModel时,你可以选择使用Android Jetpack中的其他架构组件来进一步提高开发效率,比如通过LiveData实现数据的观察和通知,或者通过DataBinding来实现UI与数据的自动绑定。 总之,ViewModelAndroid Jetpack中非常重要的一个架构组件,它的出现实现了数据与UI的解耦,提高了开发效率,并且解决了数据丢失的问题。希望通过这篇文档的详解,你对ViewModel有了更深入的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值