Android Jetpack-LiveData

89 阅读1分钟

LiveData 简介

LiveData is an observable data holder class. Unlike a regular observable, LiveData is lifecycle-aware, meaning it respects the lifecycle of other app components, such as activities, fragments, or services. This awareness ensures LiveData only updates app component observers that are in an active lifecycle state.

简单翻译一下:LiveData 是一个可观察的数据持有类,不想常规的可观察对象,LiveData 具有生命感知能力,意味着它遵循app其他组件的生命周期,例如Activity,Fragment或者是Service。感知能力可以确保LiveData只有在观察者生命周期处于活跃状态的时候进行更新app 组件

使用实例

  1. 定义ViewModel
package zeng.qiang.jetpack.livedata

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class LivedataViewModel : ViewModel() {
    val num by lazy {
        MutableLiveData(0)
    }
}
  1. 定义Activity
package zeng.qiang.jetpack.livedata

import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import androidx.activity.ComponentActivity
import androidx.lifecycle.ViewModelProvider
import zeng.qiang.jetpack.R
import kotlin.concurrent.thread

class LiveDataActivity : ComponentActivity() {
    companion object {
        val TAG: String = LiveDataActivity::class.java.simpleName
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_livedata)
        // 获取ViewModel
        val tv = findViewById<TextView>(R.id.tv)
        val btn = findViewById<Button>(R.id.btn)
        val vm = ViewModelProvider.NewInstanceFactory().create(LivedataViewModel::class.java)
        vm.num.observe(this) {
            Log.d(TAG,"onChange:$it")
            tv.text = it?.toString() ?: "empty"

        }

        btn.setOnClickListener {

            thread {
                vm.num.value = vm.num.value?.inc()

            }.start()
        }
    }
}

上述示例中,setValue()方法在子线程中更新UI会导致抛异常,因为setValue()方法只能在UI线程中调用

在thread中可以通过 postValue()更新UI

代码为:

btn.setOnClickListener {

    thread {
        for (i in 0..99) {
            vm.num.postValue(vm.num.value?.inc())
            Log.d(TAG, "循环更新UI,第$i 次")
        }
    }

}

但是 postValue存在丢数据问题,继续上例子:

btn.setOnClickListener {

    thread {
        for (i in 0..99) {
            vm.num.postValue(vm.num.value?.inc())
            Log.d(TAG, "循环更新UI,第$i 次")
        }
    }

}

打印结果为:

image.png

总结:当postValue快速调用时,会存在数据丢失问题

循环调用setValue结果如何呢?

打印结果为:

总结:当postValue快速调用时,不会存在数据丢失问题