当我们开发需求时,经常会遇到这样的情况,与UI相关的数据可能在程序运行期间发生变化,当数据发生变化时需要更新 UI展示,开发者可以通过回调或者其他方式进行监听,但这样的实现代码冗余,不好维护,而且当这种数据很多时,代码会显得臃肿不堪。为此,Jetpack提供了一个新的组件——LiveData。
LiveData译为实时数据。它实际上是一种可被观察的数据容器,将具体的数据包装起来作为被观察者,当数据内容发生变化时,观察者能够监听到数据的变化,这种方式本质上就是观察者模式,但不需要开发者具体去实现,LiveData已经都封装好了。
LiveData是一种数据容器,而之前提到的ViewModel也是数据容器,但两者还是有很大区别的。ViewModel用来存放与View或者是业务逻辑相关的数据,由于其生命周期的特性,不会随着UI组件的变化而变化,同时可以在ViewModel中做一些与业务逻辑相关的转化等等。LiveData可以理解为一种特殊的数据类型,就是对普通数据的一次再封装,使得在数据变化时观察者能够检测到。LiveData一般与ViewModel结合使用,在ViewModel中的数据发生变化时能够通过LiveData通知到View。
基本使用
LiveData是一个抽象类,在实际开发中最常用的是它的子类:MutableLiveData,示例代码如下:
class LiveDataViewModel : ViewModel() {
var mData: MutableLiveData<String>? = null
fun getData(): MutableLiveData<String> {
if (mData == null) {
mData = MutableLiveData()
}
return mData!!
}
override fun onCleared() {
super.onCleared()
}
}
首先创建ViewModel,在ViewModel类中定义一个MutableLiveData属性,需要为其正范型,该范型类型表示LiveData所持有的数据类型。然后对LiveData属性编写get方法。
与View通信:
class LiveDataActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_live_data)
setSupportActionBar(findViewById(R.id.toolbar))
var viewModel = ViewModelProvider(this).get(LiveDataViewModel::class.java)
var i = 0
findViewById<FloatingActionButton>(R.id.fab).setOnClickListener { view ->
viewModel.getData().value = i++.toString()
}
viewModel.getData().observe(this,
Observer<String> { t -> live_data_tv.setText(t ?: "null") })
}
}
调用ViewModel的get方法得到LiveData对象,调用其observe()方法,就可以监听LiveData中的数据变化,如果想要主动更新LiveData数据,执行postValue()方法或者是setValue()方法,postValue()方法用来在子线程中更新数据,setValue()方法用来在主线程中更新。
要注意,LiveData调用observe()方法监听数据时,只有当页面处于活跃状态才检测到数据变化,当页面销毁时会自动取消LiveData与页面组件的关联,避免内存泄漏。LiveData还提供了observeForever()的方法,类似于observe(),也是用来监听数据变化的,但根据名字可以知道,observeForever()方法无论页面处在什么状态下都能接收到数据变化的通知,为了避免内存泄漏,需要在页面销毁的时候需要removeObserver()。