Android ViewModel实现和原理

前言

ViewModel的主要基于观察者的设计模式,他主要分为两个部分:

  1. 提供者Provider:在我们这里就是数据的提供者,当实体的数据改变的时候,会自动通知所有观察者,观察者收到通知后就可以做对应的数据。
  2. 观察者Observer:观察者注册提供程序,当提供者每次发送通知的时候,观察者就会做对应的处理。

其最终实现出来的效果就是,在代码中,一旦我们注册的实体对象里面的数据改变之后,对应的UI就会自动的进行更新,这样数据更新的代码我们只需要在观察者里面写一套,不需要反复写多套了。

提供者和观察者是一对多的关系,也就是一个提供者可以被很多个观察者注册

1. 使用

1.1 gradle准备

在用上ViewModel之前,需要在项目的build.gradle中加上如下内容,开启DataBinding。

为了写ui方便我把ViewBinding也加上了,他不是必须的,但是我的demo代码里面会有ViewBinding相关内容。

android {
	buildFeatures {
		dataBinding = true
        viewBinding = true
    }
}

1.2 模拟场景

我们模拟一个简单的场景,页面里面就三个TextView,两个按钮,我们的目标就是用ViewModel来完成点了按钮之后他的Text就动态修改的功能。

实体是我随便设置的

class Student(var name: String = "",
              var age: Int = 0,
              var id: String = "")

页面长这样,三个TextView和两个按钮
在这里插入图片描述

1.3. LiveData和ViewModel

任何一个ViewModel的动态更新都需要围绕LiveData和ViewModel这两个类进行

LiveData:将实体动态化,可以被具有生命周期的对象观察到,只有这个目标对象的生命周期处于活动中,才会收到通知。
ViewModel:通信类,LiveData通过ViewModel来下发通知。

所以我们的代码最后写成这样:
ViewModel作为容器类,里面的成员变量是一个Student的LiveData类(一般都用MutableLiveData,如果有特殊需求也可以自己写)。
如果实际开发的时候有多个这样需要通信的实体,都丢到自定义的ViewModel类里面

class StudentViewModel : ViewModel() {
   
   
    private var student = MutableLiveData<Student>()

    fun getStudent(): MutableLiveData<Student> {
   
   
        return student
    }
}

注册通知的方式也很简单,先通过ViewModelProvider生成一个ViewModel的实体,然后将对应的实体进行观察者的注册即可。

lass ViewModelActivity : AppCompatActivity() {
   
   

    private lateinit var binding: ActivityViewModelBinding
    private lateinit var viewModel: StudentViewModel

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
   
   
        super.onCreate(savedInstanceState)

        binding = ActivityViewModelBinding.inflate(layoutInflater)
        setContentView(binding.root)

		// 创建ViewModel实体的固定写法
        viewModel = ViewModelProvider(this).get(StudentViewModel::class.java)
        // 注册Student对象,这样Student这个对象一旦改变,就会自动调用这里面的方法
        viewModel.getStudent().observe(this) {
   
   
            binding.vmName.text = "姓名:${
     
     it.name}"
            binding.vmAge.text = "年龄:${
     
     it.age}"
            binding.vmId.text = "id:${
     
     it.id}"
        }
    }
}

1.4 更新数据

更新数据有两种方式:
setValue:整个对象改变之后,他会自动的通知更新。
post:只改变目标对象里面的一两个成员变量时,通过Post进行更新。

class ViewModelActivity : AppCompatActivity() {
   
   

    private lateinit var binding: ActivityViewModelBinding
    private lateinit var viewModel: StudentViewModel

    @SuppressLint
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值