您现在的位置是:首页 >其他 >Android - LiveData(MutableLiveData)网站首页其他
Android - LiveData(MutableLiveData)
一、介绍
LiveData是Jetpack提供的一种响应式编程组件,它可以包含任何类型的数据,并在数据发生 变化的时候通知给观察者。LiveData特别适合与ViewModel结合在一起使用,虽然它也可以单 独用在别的地方,但是在绝大多数情况下,它是使用在ViewModel当中的。
二、使用
class PublishViewModel : ViewModel() {
var content = MutableLiveData<Int>()
fun contentTop() {
val contents = content.value ?:0
content.value = contents+1
}
fun contentBt() {
content.value = 0
}
}
将counter变量修改成了一个MutableLiveData对象,并指定它的泛型为Int,表 示它包含的是整型数据。
MutableLiveData是一种可变的LiveData,它的用法很简单,主要 有3种读写数据的方法,分别是getValue()、setValue()和postValue()方法。 getValue()方法用于获取LiveData中包含的数据;
setValue()方法用于给LiveData设置数 据,但是只能在主线程中调用;
postValue()方法用于在非主线程中给LiveData设置数据。
而上述代码其实就是调用getValue()和setValue()方法对应的语法糖写法。
可以看到,这里在init结构体中给counter设置数据,这样之前保存的计数值就可以在初始化 的时候得到恢复。接下来我们新增了Top()和Bt()这两个方法,分别用于给计数加1 以及将计数清零。
Top()方法中的逻辑是先获取counter中包含的数据,然后给它加1, 再重新设置到counter当中。
注意调用LiveData的getValue()方法所获得的数据是可能为空 的,因此这里使用了一个?:操作符,当获取到的数据为空时,就用0来作为默认计数。
主页面
class PublishActivity : BaseActivity() {//换成AppCompate()
lateinit var viewModel: PublishViewModel
lateinit var sb_content_value: TextView
@SuppressLint("ResourceType", "MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.publish_activity_publish)
initViewModel()
initView()
observe()
}
@SuppressLint("SetTextI18n")
private fun observe() {
viewModel.content.observe(this, {
sb_content_value.text = it.toString()
})
}
private fun initView() {
//Snackbar
findViewById<Button>(R.id.fab).setOnClickListener { view ->
viewModel.contentTop()
Snackbar.make(view, "++", Snackbar.LENGTH_LONG)
.setAction("撤消") {
viewModel.contentBt()
}.show()
}
//
sb_content_value = findViewById(R.id.sb_content_value)
}
private fun initViewModel() {
viewModel = ViewModelProvider(this).get(PublishViewModel::class.java)
}
}
这里调用了viewModel.counter的observe()方法来观察数据的 变化。经过对MainViewModel的改造,现在counter变量已经变成了一个LiveData对象,任 何LiveData对象都可以调用它的observe()方法来观察数据的变化。observe()方法接收两 个参数:第一个参数是一个LifecycleOwner对象,有没有觉得很熟悉?没错,Activity本身 就是一个LifecycleOwner对象,因此直接传this就好;第二个参数是一个Observer接口, 当counter中包含的数据发生变化时,就会回调到这里,因此我们在这里将最新的计数更新到 界面上即可。
三、注意
如果你需要在子线程中给LiveData设置数据,一定要调用postValue()方法, 而不能再使用setValue()方法,否则会发生崩溃。
另外,关于LiveData的observe()方法,我还想再多说几句,因为我当初在学习这部分内容时 也产生过疑惑。observe()方法是一个Java方法,如果你观察一下Observer接口,会发现这 是一个单抽象方法接口,只有一个待实现的onChanged()方法。既然是单抽象方法接口,为什 么在调用observe()方法时却没有使用Java函数式API的写法呢?
这是一种非常特殊的情况,因为observe()方法接收的另一个参数LifecycleOwner也是一个 单抽象方法接口。当一个Java方法同时接收两个单抽象方法接口参数时,要么同时使用函数式 API的写法,要么都不使用函数式API的写法。由于我们第一个参数传的是this,因此第二个参 数就无法使用函数式API的写法了。
不过在2019年的Google I/O大会上,Android团队官宣了Kotlin First,并且承诺未来会在 Jetpack中提供更多专门面向Kotlin语言的API。其中,lifecycle-livedata-ktx就是一个专门为 Kotlin语言设计的库,这个库在2.2.0版本中加入了对observe()方法的语法扩展。我们只需要 在app/build.gradle文件中添加如下依赖:
dependencies {
...
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
}
然后就可以使用如下语法结构的observe()方法了:
viewModel.counter.observe(this) { count ->
infoText.text = count.toString()
}