说实话,一开始接触LiveData的概念,是通过郭神的《第一行代码(第三版)》,但是一股脑的各种概念铺天盖地而来,导致的后果就是面对LiveData莫名地有种恐惧,所以这也是我开始专门研究Jetpack的一个初衷(题外话,在小公司写传统业务代码,真的是可以用10年前的技术吃一辈子,严重脱节)。
一、LiveData原理
说回LiveData,可以将LiveData理解为一个数据的容器,它将数据包装起来,使数据成为被观察者,当该数据发生变化时,观察者能够获得通知。由于在LiveData内部默认已经实现好了观察者模式,所以我们只需要使用就可以了。
一般来说,我们都会讲LiveData和ViewModel一同使用,它们的关系大概如下图这样:
我们会在ViewModel存放页面所需要的各种数据,以及处理一些与数据相关的的逻辑,因此,ViewModel中的数据可能会随着业务的变化而变化。
对于页面来说,仅仅关心需要展示的数据,并且希望在数据发生变化时,能及时得到通知并作出更新。LiveData的作用就是,在ViewModel中的数据发生变化时通知页面。因此,LiveData通常被放在ViewModel中使用,用于包装ViewModel中那些需要被外界观察的数据。
查看LiveData的源码可知,LiveData是一个抽象类,因此不能直接使用。通常我们使用的是它的直接子类MutableLiveData。
现在我们需要在页面中点击按钮,点击一下显示的数字加1,因此,ViewModel部分可以这么写:
//每个Activity和Fragment都创建一个对应的ViewModel
//所有与界面相关的数据都应该存放在这里
//实现计数器功能
class MainViewModel(countReserved:Int):ViewModel(){
val counter:LiveData<Int>//LiveData将数据的变化通知给Activity
get()=_counter
private var _counter = MutableLiveData<Int>()
init {
_counter.value = countReserved//记录之前保存的计数值
}
fun plusOne(){
val count = _counter.value?:0
_counter.value = count+1//counter.setValue()只能在主线程中调用.PostValue()用于非主线程中给LiveData设置数据
}
fun clear(){
_counter.value = 0
}
}
在页面中可以这么调用:
class MainActivity : AppCompatActivity() {
lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this,MainViewModelFactory(countReserved)).get(MainViewModel::class.java)//获取ViewModel的实例,将countReserved传递给MainViewModel的构造函数
viewModel.counter.observe(this, Observer {
count->
infoText.text = count.toString()
})
}
fun plusOneClick(view:View){
viewModel.