关于ViewModel的这几个问题,你都知道吗?

前言

作为一名Android开发者,如果你熟悉MVVM架构,熟悉Jetpack组件,那么相信你肯定使用过ViewModel

正如它的名字一样,它是Google推出的一个类javaee,方便我们实android是什么手机牌子MVVM架构中的Vimvvm原理ewModel层。我们在其中处理View层所需的数据,然后在特定条件下通知View层进行javascriptUI更新

正如官方所介绍:

ViewModel 类以注重生命周期的方式存储和管理界面相关的数据ViewModelmvvm原理 类让数据可在发生屏幕旋转等配置更改后继续留存

我们抓一下这句话的重点:

  1. 注重生命周期的方式:会在合适的时间进行自我回收,防止出现内存泄漏。
  2. 存储和管理界面相关的数据:符合MVVM架构ViewModel层的理念。
  3. 在发生屏幕旋转等配置更改后继续留存数据:为javaee什么要这么设计?怎么做到的。

接下来,就让我们带着问题,深入学习一下Viandroid是什么系统ewMojava语言del类。

使用方法

在阅读源码前,mvvm数据双向绑定原理让我们先来简单回顾一下ViewModel的使架构师证书用方法。

class MainViewModel(private val repository: MainRepo) : ViewModel() {
    private val _textMld = MutableLiveData<String>()
    val textLd: LiveData<String> = _textMld
    fun getTextInfo() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                //做异步网络请求工作,获取到textData
                repository.getTextInfo()
            }.apply {
                _textMld.postValue(textData)
            }
        }
    }
}
class MainActivity : AppCompatActivity() {
    fun setVmFactory(): ViewModelProvider.Factory {
        return object : ViewModelProvider.Factory {
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                return MainViewModel(MainRepo()) as T
            }
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        val vm = ViewModelProvider(this, setVmFactory())[MainViewModel::class.java]
        vm.textLd.observe(this, Observer { 
            binding.textTv.text = it
        })
    }
}

方法步骤可以简单分为两步,分别为:

  1. 继承View架构图模板Model类实现自定义ViewModel,如java培训:MainViewModel。
  2. 通过ViewModelProvidermvvm模型实例化ViewModel

源码

现在,根据上方所介绍的使用方法,我们进一步来看一下ViewMo架构图模板del的源码。

public abstract class ViewModel {
    ....
    @SuppressWarnings("WeakerAccess")
    protected void onCleared() {
    }
    @MainThread
    final void clear() {
        ....
        onCleared();
    }
    ....
}

ViewModel 是一个抽象类,提供 onCleared()方法mvvm和mvc供我们在ViewMmvvm和mvcodel销毁前做一下清mvvm数据双向绑定原理除工作。

接下来,我们来看看是如何通过ViewModelProvider来实例化Vjava环境变量配置iewModel对象的。

其实就是两步:

  1. 实例化一个 ViewModelProvider 对象。
  2. 调用 ViewModelProvider.get()方法架构是什么意思来得到一个ViewModel对象。

先来看看它的构造函数:

public open class ViewModelProvider(
    private val store: ViewModelStore,
    private val factory: Factory
) {
	public constructor(
	    owner: ViewModelStoreOwner
	) : this(owner.viewModelStore, defaultFactory(owner))
	public constructor(owner: ViewModelStoreOwner, factory: Factory) : this(
	    owner.viewModelStore,
	    factory
	)
......
}

通过 ViewModeljava编译器Provider 的构造函数可以看出,一共有两个参数:ViewModelStoreFactory

分别来看看架构设计这两个参数代表着什么意思。

public class ViewModelStore {
    private final HashMap<String, ViewModel> mMap = new HashMap<>();
    final void put(String key, ViewModel viewModel) {
	//所以这里key需要注意,不要使用相同的key,否则后创建的VM会替换到老的VM
        ViewModel oldViewModel = mMap.put(key, viewModel);
        if (oldViewModel != null) {
            oldViewModel.onCleared();
        }
    }
    final ViewModel get(String key) {
        return mMap.get(key);
    }
    Set<String> keys() {
        return new HashSet<>(mMap.keySet());
    }
    public final void clear() {
        for (ViewModel vm : mMap.values()) {
            //调用ViewModel的clear方法,表示不再使用
            vm.clear();
        }
	//清除集合中的所有ViewModel
        mMap.clear();
    }
}

ViewModelStore:正如其名,就是用来存储ViewModel对象的,通过内部维护一个HashMap来实现对Vieandroid平板电脑价格wMoel对象的存储与管理工作。

再来看看上面所介绍的 Factory

而Factory则是工厂接口的,用来实例化ViewModel,具体实现可以参考使用方法中所介绍android的drawable类setVmFactor架构工程师y() 方法,用来实例化 MainViewModel。

public interface Factory {
    public fun <T : ViewModel> create(modelClass: Class<T>): T
}

接下来,我们来看看 ViewModelProvider 中的 get(mvvm和mvc) 方法。

public open operator fun <T : ViewModel> get(modelClass: Class<T>): T {
    val canonicalName = modelClass.canonicalName
    return get("$DEFAULT_KEY:$canonicalName", modelClass)
}
public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
    //1.根据key从ViewModelStore中取出ViewModel
    var viewModel = store[key]
    //2.通过工厂方法来实例化viewModel
    if (modelClass.isInstance(viewModel)) {
        (factory as? OnRequeryFactory)?.onRequery(viewModel)
        return viewModel as T
    }
    viewModel = if (factory is KeyedFactory) {
        factory.create(key, modelClass)
    } else {
        factory.create(modelClass)
    }
    //3.将实例化的ViewModel放入ViewModelStore
    store.put(key, viewModel)
    return viewModel
}

概括一下 get() 方法:

  1. 根据传入的形参Class.canonicalName做为kjavaeeey,从ViewModelStore中取出ViewMmvvm数据双向绑定原理odel。
  2. 再通过工厂方法来实例化V架构图模板iewModel。androidstudio安装教程
  3. 最后将实例化后的ViewModel放入ViewMo实例化delStore中,并返回。

OK,根据使用方法来java培训分析源码的话,我们好像已经分析完了。本篇文章到此结束?

这还远远android平板电脑价格不够!

不知你有没有想过它为什么会取名叫做Vijava培训ewModel呢?它跟MVVM架构模式中的ViewModel是怎么样的一种关系呢?它又是怎么感知到生命周期的呢?为什么要设计成屏幕旋转后继续留存ViewModel呢?

接下来,让我们带着问题,进一步进行学习思考。

为什么要叫做ViewModel

这其实就是Google架构工程师设计这个类的初衷mvvm的理解问题了。我们知道在Android的架构模式中,从最初始的MVC,到MVP,Google其实没有专门为了这架构模式而设计一些类来支持提供我们开发者使用,这也间接导致开发者会拥有一套属于自己的设计风格。直到MVVM架构模式的出现,Google为了减小开发者架构难度,提升开发效率,为我们新设计了一些类来支持MVVM架构模式,其中就有ViewModel这个类,用来处理MVVM模式中ViewModel层所负责的工作。这也就是为什么它会被命名叫做ViewModel

ViewModel是如何感知到生命周期的

正如官网所介绍的,Vimvvm模型ewModel是有生命周期的,如下图所示:

关于ViewModel的这几个问题,你都知道吗?

不知你有没有思考过ViewMoandroid下载del是如何感知实例化到生命周期的呢?

如果你熟悉 Jetpack 的话,你肯定会脱口而出答案:Lifecycle。事实也证明的确是通过 Lifecycle 来感知到生命周期的。

其实官方文档也介绍了:

View实例化一个对象可以使用什么命令Model 对象存在的时间范围是获取 Vijava模拟器ewModel 时传递给 ViewModelProviderLifecycle。ViewModel 将一直留在内存android平板电脑价格中,直到限java模拟器定其存在时间范围的 Lifecycle 永久消失.

那接下来android的drawable类就让我架构师工资们来进一步看看ViewModel是如何拿到Lif实例化对象ecycle来感知到生命周期的。

还记得使用方法中所介绍的使用ViewModelProvider来实例化Vijava编译器ewModel吗?

val viewModel = ViewModelProvider(this, setVmFactory())[getViewModelClass()]

关于 ViewModelProvider的构造函数,我们之前已经android平板电脑价格介绍过了,分别是ViewMoandroid手机delStoreFactorjava语言y。回到调用方法里,这里的Javathis就是指当前所在的Activity,也对应着构造函数中的ViewModelStore

Activity 对应 ViewModelStore ?这是什么对应关系?

java是什么意思时,我扫了一眼 ViewModelStmvvm模式ore 类注释,发现了一句话:

Use {@link ViewMoandroidstudio安装教程delStoreOwner#getViewModjava面试题elStore()} to retrieve a {@code ViewModelStore} f实例化是什么意思or activities and fragments.

通过 ViewModelStoreOwner#getViewModelStandroid手机ore() 方法来给 Actjava环境变量配置ivity、Fragment 获取到 View架构工程师M架构师odelStore

public interface ViewModelStoreOwner {
    /**
     * 返回 ViewModelStore
     */
    @NonNull
    ViewModelStore getViewModelStore();
}

到这一步,应该想到了吧,我android手机们的 Activity | Fragment 实现android什么意思ViewMomvvm每个字母代表的含义delStoreOwnjava环境变量配置er接口,并实现了getViewModelStore()方法来得到 ViewModelStore

果然,Activity的父类ComponentActivity类实现了ViewModelStoreOwner接口并实现了getView实例化一个对象可以使用什么命令Model实例化对象Store()接口方法。

ComponnetActivity.kt
public class ComponentActivity extends androidx.core.app.ComponentActivity implements
        LifecycleOwner,
        ViewModelStoreOwner
	...... {
	public ViewModelStore getViewModelStore() {
            //检查一下当前 mViewModelStore 是否为空
	    if (mViewModelStore == null) {
		//检索一下是否有先前保存的非配置实例数据
	        NonConfigurationInstances nc =
	                (NonConfigurationInstances) getLastNonConfigurationInstance();
	        if (nc != null) {
                    //从先前保存的非配置实例数据中取出 ViewModelStore
	            mViewModelStore = nc.viewModelStore;
	        }
	        if (mViewModelStore == null) {
                    //先前没有保存过非配置实例数据,则新建一个 ViewModelStore
	            mViewModelStore = new ViewModelStore();
	        }
	    }
	    return mViewModelStore;
	}
}

简单概括一下:在获取 ViewModelStore 这一步中,android的drawable类会先去检索一下是否有先前保存的非配置实例数据,如果有保存,则取出其中的 ViewModelStore; 反之,如果之前没有保存过,则新创建一个 ViewModelStore

所以,在 ViewModelProvider 的构造函android下载安装数中通过调用owner.viewMmvvm框架odelStore 方法来获取到 viewModelStore,这一步其实就是取在 Activity | Fragmen架构是什么意思tgetViewModelStore()方法中创java编译器建的 ViewModelStore,也就是我们刚刚所介绍的。

到了这,好像也没有看出跟 L架构师工资ifecycle 有任何关系啊。

接着我们进一步看看 viewModelStoreLifecycle 之间的调用关系。

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()) {
                    //调用ViewModelStore中的clear()方法来清除其ViewModel
                    getViewModelStore().clear();
                }
            }
        }
    });
    ......
}

通过Lifecycle来感知Activity的生命周期,当Activity处于销毁状态时,检查一下是否发生配置变更,如果未发生配置变更,则调用clear()方法来清除ViewModelStore及其保存mvvm原理ViewModel

关于配置类的实例化变更,我们放到文章后面来分析,这里先不展开。

总结一下ViewModel是如何感知java编译器到生命周期的。实例化对象

首先我们知道ViewModel是存储在ViewModelStore中的,当我们进入Activity时,会自动创建一个ViewModelStore,当我们在onCreate()方法中调用ViewModelProvider.get()方法时,就会将创建的ViewModel存到该ViewModelStore中。通过Lifecycle来得知Activity的生命周期,当Activity处于销毁时,检查一下是否发生配置变更,如果未发生配置变更,则调用cle架构师证书ar()方法来清除ViewModejavascriptlStore及其保存的ViewModel

为什么屏幕旋转后ViewModel数据可以继续留存

当我们没有为Activity设置 configChanges 属性java面试题时,Activity会在架构工程师我们旋转屏幕时发生重建,而此时ViewModel会继续留存这mvvm数据双向绑定原理些数据。

这是如何做到mvvm原理的呢?

正如上文中所提到的,当Activity处于销毁时,会去检查一下是否发生配置变更,如果未发生配置变更,则调用clear()方法来清除ViewModelStore及其保存的ViewModel

那这么看的话,想必我们在mvvm的理解旋转屏幕时,是发生了配置变更的,因为正mvvm模式是发生了配置变更才让我们的ViewModel没有被清除掉,得以留存这些状态数据。

当Activity因为配置更改(如:旋转屏幕)而被销毁重建时,系统会立即调用onRetainNonConfigurationInstance()方法。

ComponentActivity.java
public final Object onRetainNonConfigurationInstance() {
    // Maintain backward compatibility.
    Object custom = onRetainCustomNonConfigurationInstance();
    ViewModelStore viewModelStore = mViewModelStore;
    if (viewModelStore == null) {
        //获取先前创建的非配置实例数据
        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            viewModelStore = nc.viewModelStore;
        }
    }
    if (viewModelStore == null && custom == null) {
        return null;
    }
    //如果先前没有创建过非配置实例数据,则新创建一个,并返回。
    NonConfigurationInstances nci = new NonConfigurationInstances();
    nci.custom = custom;
    nci.viewModelStore = viewModelStore;
    return nci;
}
static final class NonConfigurationInstances {
    Object custom;
    ViewModelStore viewModelStore;
}

会先通过 getLastNonConfigurationInstance() 方法来获取先前创建的非配置实例数据,如果先前没有创建过非配置实例数据,则新创建一个,并返回。

Activity.java
NonConfigurationInstances mLastNonConfigurationInstances;
public Object getLastNonConfigurationInstance() {
    return mLastNonConfigurationInstances != null
            ? mLastNonConfigurationInstances.activity : null;
}
final void attach(NonConfigurationInstances lastNonConfigurationInstances ...) {
    ...
    mLastNonConfigurationInstances = lastNonConfigurationInstances;
    ...
}
static final class NonConfigurationInstances {
    Object activity;
    HashMap<String, Object> children;
    FragmentManagerNonConfig fragments;
    ArrayMap<String, LoaderManager> loaders;
    VoiceInteractor voiceInteractor;
}

可以看出,mLastNonConfiguratJavaionInstances 是在Activity的 attach() 方法中被赋值的,所以我们需要android手机往上看Activity的启动流程。

ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	......
    Activity activity = null;
    activity.attach(r.lastNonConfigurationInstances ...);
    r.lastNonConfigurationInstances = null;
	......
    return activity;
}

也就是说最初始的非配置实例是在Actiandroidstudio安装教程vityThread中的ActivityClientRecorandroid是什么手机牌子d所创建的,当Activity发生配置变更而重建时ActivityClientRecord是不受影响的,所以这样当屏java环境变量配置幕旋转Activity重建(配置变更)时,先是JavaonRetainNonConfigurationInstance() 方法会被调用返回一个包含当前ViewModelStore的非配置实例对象,然后后续通过getLastNonConfigurationInstance()方法来获取到该非配置实例,所以架构师保存在其ViewMode类的实例化lStore中的ViewModel是不是被清除的。

关于配置变更,这里补充一点。

  • 旋转屏幕其实就是一次配置变更,isChangingConfigurations = true。
  • 当跳转mvvm原理面试到另外一个Activmvvm和mvcitmvvm模型y时(Activity正常退出或系统java编译器杀死)配置未变更,isChangingConfigurations = false。

为什么要设计成配置变更后ViewModAndroidel依然存在

现在我们知道当Activity发生配置变更重建的时,ViewModel是不会被清除的,所以他保存的数据依然存在。

不知你有没有想过,为什么要这么设计呢?

我们知android的drawable类道ViewModel类负责处理的是MVVM架构模式ViewModel层的工作,所以MVVMViewModel保留的是UI状态数据。当你屏幕旋转时,Activity会android是什么系统发生重建工作,将我们的xml布局从portrait切换到了landscape,但其实布局中展示的数据是一样的。所以,我们完全不需要再去Model层重新获取一下数据,直接复用ViewModel中保留的android是什么系统数据即可,从而节省系统开销。

另外,在ViewModel出现之前,当我们想要在实例化Activity发生销毁重建时保留数据需要通过覆写 onSaveInstanceState() 方法来实现,该方法通过Bundle来将数据序列化保存在android是什么手机牌子磁盘中,实现步骤相对复杂且又有大小限制。相对比,ViewModel将数mvvm的理解据保存在内存中,读写速度更快,而且又没有大android什么意思小限制,所以是一种很好的替代方案。

总结

本篇文章,我们通过ViewModel的使用方法来学习了ViewModel的源码,又对ViewModel的设计进行了进一步思考,就 “它为什么会取名叫JavaViewModmvvm数据双向绑定原理el?它跟MVVM中的ViewModel是怎么样的一种关系?他又是怎么感知到生命周期的?为什么要设计成屏幕旋转后继续留存ViewModel?”实例化对象 这几个问题进行了进一步的学习,相信你现在对ViewModel有了进一步java语言的认识与理解。

到此本篇文章就结束啦,如果你有任何疑问架构师或者不同的想法,欢迎在评论区留言与我一起探讨。

其实分享文章的最大目的正是等待着有人指出我的错误,如果你发现哪里有错误,请毫无保留javascript的指出即可,虚心请教。

另外,如果你觉得文章不错,对你有所帮助,请帮我点个赞,就当鼓励,谢谢~。实例化是什么意思

发表评论

提供最优质的资源集合

立即查看 了解详情