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()
}

猜你喜欢

转载自blog.csdn.net/m0_59482482/article/details/130205216