前言

最近项目中有用到LiveData+ViewModel的架构组件,今天来学习一波。本篇文章参考:MVVM 架构,ViewModel和LiveData
所有语言为Kotlin。


LiveData

LiveData是一个可以被观察的数据持有者.这也就意味着应用中的组件能够观察LiveData对象的更改,而无需在它们之间创建明确的和严格的依赖关系。这将完全分离LiveData对象使用者和LiveData对象生产者。
除此之外,LiveData还有一个很大的好处,LiveData遵守应用程序组件(活动,片段,服务)的生命周期状态,并进组件的生命周期管理,确保LiveData对象的内存泄漏。
注:上述的遵守应用程序组件的生命周期是指,譬如说Activity的生命周期在onStart、onResume的状态下是可以接收到LiveData内的数据变化回调的。而在Stop之后数据变化不会进行回调。而且在Activity销毁的时候,LiveData也会随之销毁,简单理解为它和Activity的生命周期类似,这也防止了内存泄漏。

在开发中我们多用的是继承LiveData的子类MutableLiveData<T>。里面还有两个方法,setValue和postValue,setValue必须在主线程调用。postValue可以在后台线程中调用。


ViewModel

ViewModel是和Model(数据层)进行交互,并且ViewMode可以被View观察.ViewModel可以选择性地为视图提供钩子以将事件传递给模型.该层的一个重要实现策略是将Model与View分离,即ViewModel不应该意识到与谁交互的视图。

通俗地来说,ViewModel所承担的职责就是UI层与数据层的中间层。

  • 一方面可以减轻View层的逻辑,View层可以更好的针对UI做设置而无需考虑其他逻辑。
  • 另一方面ViewModel作为View和Model的中间层,将View和Model解耦合。

此外,ViewModel还有一个比较厉害的功能,通常情况下activity会被系统自动销毁,此时我们用于保存数据的方式就是事先在onSaveInstanceState()方法中规定好需要存储的数据。但是这种做法有一个缺点就是保存的数据要经过序列化。使用ViewModel的话ViewModel会自动保留之前的数据并给新的Activity或Fragment使用。直到当前Activity被系统销毁时,Framework会调用ViewModel的onCleared()方法,我们可以在onCleared()方法中做一些资源清理操作。


使用ViewModel+LiveData编写一个简易demo

1、首先我们需要编写一个实体类,用于数据的封装:

`data class AccountBean(

    val name:String = "",
    val number:String = "")`

2、创建一个自定义的ViewModel:

`class AccountModel : ViewModel() {
    val accountLiveData = MutableLiveData<AccountBean>()

    fun getData(){
        accountLiveData.value = AccountBean("cyber","2077")
    }

    override fun onCleared() {
        super.onCleared()
    }
}`

在这个ViewModel里面我们定义了一个MutableLiveData的对象其本质就是一个LiveData,而这个LiveData里的数据绑定的是刚刚我们定义的实体类型AccountBean。
getData方法是用于模拟数据更新的,当调用此方法时,我们会设置上述的LiveData里的数据内容。上述的accountLiveData.value实际上是调用了MutableLiveData里的setValue方法。

3、View层的编写
接下来就是View层了,其实就是Activity层

xml:

`<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:text="Hello World!"
        app:layout_constraintBottom_toTopOf="@+id/button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_chainStyle="packed" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="217dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/text" />

</android.support.constraint.ConstraintLayout>`

kotlin:

`class MainActivity : AppCompatActivity() {

    private lateinit var mAccountModel:AccountModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //初始化ViewModel
        mAccountModel= ViewModelProviders.of(this).get(AccountModel::class.java)
        //点击按钮后更新LiveData的数据实体
        button.setOnClickListener{
            mAccountModel.getData()
        }
        //设置LiveData的观察者相应更新TextView
        mAccountModel.accountLiveData.observe(this, Observer {
            text.setText("名字:${it!!.name},号码:${it!!.number}")
        })
    }
}`

界面很简单,就是一个TextView和一个Button。
首先我们需要将刚刚写好的ViewModel作为对象创建出来然后再onCreate时候初始化,这里需要注意的是Kotlin默认定义对象时需要初始化,所以这里使用lateinit关键字来声明对象需要延迟初始化。
点击按钮的时候,我们模拟数据更新调用刚刚在自定义ViewModel中的getData方法更新LiveData里的数据。
此处我们注册了LiveData的观察模式,当数据发生变化时会回调上述的observe方法,而在Observer对象中其实是有一个onChange方法的,上述的it代表的其实就是刚刚改变的那个数据(AccountBean对象)。

标签: LiveData+ViewModel

添加新评论