阅读 3658

Android从零开始搭建MVVM架构(2)————ViewModel

在真正接触并使用MVVM架构的时候,整个人都不好了。因为个人觉得,MVVM相对于MVC、MVP学习难度比较大,设计的知识点不是一点半点。所以想慢慢记录下自己的成长。如有错误希望指正。


从零开始搭建MVVM架构系列文章(持续更新):
Android从零开始搭建MVVM架构(1)————DataBinding
Android从零开始搭建MVVM架构(2)————ViewModel
Android从零开始搭建MVVM架构(3)————LiveData
Android从零开始搭建MVVM架构(4)————Room(从入门到进阶)
Android从零开始搭建MVVM架构(5)————Lifecycles
Android从零开始搭建MVVM架构(6)————使用玩Android API带你搭建MVVM框架(初级篇)
Android从零开始搭建MVVM架构(7) ———— 使用玩Android API带你搭建MVVM框架(终极篇)


还是那张图AAC(Android Architecture Components)

这篇我们讲ViewModel。这里我们只是简单了解和认识MVVM中的ViewModel。等把这些组件都认识后,我们再以wanAndroid api撸一遍正题的MVVM项目。


一、ViewModel

还记得MVP中的Model吗。这里的ViewModel有点类似MVP中的Model的作用。但是google出了一套AAC组件。这些组件让开发者能开发高效的项目。其中ViewModel也是其中组件之一。

1.1、为什么会有这个ViewModel组件

简介:ViewModel是以生命周期的方式存储与管理UI相关数据
作用
1、在MVVM模式中,使Model与View分离
2、负责为ui准备数据
3、存储数据

这里最大的亮点是以生命周期的方式。举例:假如在Activity里使用。他会贯穿整个Activity里的生命周期。先看张图:

首先把结果先总结以下几点(后面用例子验证):

  • ViewModel只会在Activity存活,且只会创建一次。当销毁时,会主动调用onClered。

为什么整个生命周期方式很重要?例如:app需要频繁异步请求数据,比如请求网络调接口,这些都是相当耗时。比如Activity被销毁后接口请求才返回,考虑到内存泄漏情况,会给我们增添好多复杂工作。但现在我们利用ViewModel处理数据回调,可以解决此问题。意思只要继承我们的ViewModel后,可能会出现的bug,google都帮我们处理了。

  • 因为在Activity存活时,只创建一次,那么在此Activity下的所有Fragment都可以共享一个ViewModel
  • 由于 ViewModel 生命周期可能长与 activity 生命周期,所以为了避免内存泄漏Google禁止在ViewModel中持有Context或activity或view的引用。如果非得使用Context, 可以继承AndroidViewModel 类中获取ApplicationContext
  • 之前我们在activity销毁重建时,可以用activity的onSaveInstanceState()机制保存和恢复数据,但缺点明显, 只适合保存少量的可以被序列化、反序列化的数据。假如我们需要保存一个比较大的数据,这个时候ViewModel就可以实现。


怎么看上面的生命周期图呢
1、Activity created(走了3个生命周期),对应于ViewModel的scope。
2、Activity rorared(类似切换了横竖屏幕),还是对应scope
3、finish()(Activity销毁),依赖是scope
4、Finished (已经销毁了)。调用ViewModel的onCleared。

这样说很模糊,看一下例子


二、探索ViewModel的生命周期

我们首先创建我们的MyViewModel,继承ViewModel。并重写onCleared()

public class MyViewModel extends ViewModel {
    @Override
    protected void onCleared() {
        super.onCleared();
        LogUtils.i("MyViewModel的相关","Activity被杀死后也会被销毁!");
    }
}
复制代码

点开ViewModel的源码:

因为这层没有透露出具体的生命周期绑定和销毁的具体实现。我们还要去找实现类。这里我们本着简单使用的原则,那么我就直接在Activity里打印MyViewModel的hashCode值来验证上面的图,Activity里的代码。这里还要说下,这里我们用到了ViewModelProciders类,所以要引入下依赖

implementation 'android.arch.lifecycle:extensions:1.1.1'

public class ViewModelActivity extends FragmentActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_viewmodel);
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相关", "onCreate ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onStart() {
        super.onStart();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相关", "onStart ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onResume() {
        super.onResume();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相关", "onResume ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onPause() {
        super.onPause();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相关", "onPause ==> " + myViewModel.hashCode());
    }

    @Override
    protected void onStop() {
        super.onStop();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相关", "onStop ==> " + myViewModel.hashCode());
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
        LogUtils.i("MyViewModel的相关", "onDestroy ==> " + myViewModel.hashCode());
    }
}
复制代码

运行项目后,看打印;这里可以看到,hashCode值都是一样的。:

接着我们让手机横竖切换下,看打印。同样可以看到hashCode值是一样的,没有改变:

最后,我们退出这个页面,看打印。这里在调用了ViewModel的onCleared后销毁后,hashCode值才重新创建。这里唯一疑点是,这里和官网图有些不同,ViewModel的销毁onClered,在Ondestroy的前一步(只是和图解效果有差异,但是流程是对的,如有小伙伴对这块熟悉,请指点下):


三、与Fragment间共享数据

比如我们Activity里还展示了很多个Fragment。我们这里只需要看一段Fragment里的代码就清楚了

//从getActivity()这句,那可不是同一个MyViewModel吗。
ViewModelProviders.of(getActivity()).get(MyViewModel.class)
复制代码

至此这里对简单的ViewModel做了简单介绍,和使用。让我们一起慢慢实现自己的MVVM框架把!!

本文demo地址