LiveData是什么?
官方定义:LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
完全看不懂!
LiveData优势和特点
- 如果观察者(由 Observer 类表示)的生命周期处于 STARTED或 RESUMED状态,则 LiveData 会认为该观察者处于活跃状态。
- LiveData 只会将更新通知给活跃的观察者。 为观察 LiveData对象而注册的非活跃观察者不会收到更改通知。
- LiveData 遵循观察者模式。当生命周期状态发生变化时,LiveData 会通知 Observer对象。
- 观察者会绑定到 Lifecycle对象,并在其关联的生命周期遭到销毁后进行自我清理。
- 不会因 Activity 停止而导致崩溃。
- 不再需要手动处理生命周期
- 数据始终保持最新状态
- 如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据。
LiveData 类
// 抽象类
abstract class LiveData<T : Any!>
LiveData 通常是结合ViewModel一起使用。而且和ViewModel一样,同属于 【androidx.lifecycle.*】 包下
LiveData 是一个抽象类,一般不直接使用,主要使用其两个子类:
// MutableLiveData 子类
public class MutableLiveData<T> extends LiveData<T> {
@Override
public void postValue(T value) {
super.postValue(value);
}
@Override
public void setValue(T value) {
super.setValue(value);
}
}
//MediatorLiveData 子类
public class MediatorLiveData<T> extends MutableLiveData<T> {
}
LiveData使用
// 返回LiveData对象 的值
@Nullable open fun getValue(): T?
// 更新LiveData 对象的值
@MainThread protected open fun setValue(value: T): Unit
//更新LiveData 对象的值
protected open fun postValue(value: T): Unit
//观察 LiveData 对象
@MainThread open fun observe(
@NonNull owner: LifecycleOwner,
@NonNull observer: Observer<in T>
): Unit
//观察 LiveData 对象, 观察者会被视为始终处于活跃状态,
//需要通过 removeObserver(Observer) 手动移除
@MainThread open fun observeForever(@NonNull observer: Observer<in T>): Unit
可以按照以下步骤使用 LiveData:
- 1)创建 LiveData 实例以存储某种类型的数据。这通常在 ViewModel类中完成。如:
class NameViewModel : ViewModel() {
// Create a LiveData with a String
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// Rest of the ViewModel...
}
-
2)创建可定义 onChanged() 方法的Observer 对象,该方法可以控制当 LiveData 对象存储的数据更改时会发生什么。通常情况下,您可以在界面控制器(如 Activity 或 Fragment)中创建 Observer 对象。
-
3)使用 observe()方法将 Observer对象附加到 LiveData 对象。通常情况下,您可以在界面控制器(如 Activity 或 Fragment)中附加 Observer对象。
class NameActivity : AppCompatActivity() {
// Use the 'by viewModels()' Kotlin property delegate
// from the activity-ktx artifact
private val model: NameViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 创建观察者更新UI
val nameObserver = Observer<String> { newName ->
nameTextView.text = newName
}
// 观察LiveData
model.currentName.observe(this, nameObserver)
}
}
最简单示例
本实例要实现的效果是,一个简单的加法计算器。如果用户输入2个整数,求和,如果输入不正确或输入为空,则提示请输入正确。效果如下:
可以先思考一下,如果单纯使用上一节的ViewModel如何实现?ViewModel为什么要和LiveData结合呢?
Xml代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_marginTop="80dp">
<EditText
android:id="@+id/number1"
android:layout_width="100dp"
android:textSize="20sp"
android:hint="0"
android:textAlignment="center"
android:layout_height="wrap_content"/>
<TextView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:textAlignment="center"
android:text="+"
android:textSize="20sp"/>
<EditText
android:id="@+id/number2"
android:layout_width="100dp"
android:textSize="20sp"
android:hint="0"
android:textAlignment="center"
android:layout_height="wrap_content"/>
</LinearLayout>
<TextView
android:id="@+id/resultText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textAlignment="center"
android:text="0"
android:layout_marginTop="30dp"/>
<Button
android:id="@+id/addBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="="
android:textSize="30sp"
android:layout_marginTop="50dp"/>
</LinearLayout>
ViewModel 和LiveData
class MainViewModel : ViewModel() {
// 定义私有,防止外部修改
private var result: MutableLiveData<Int> = MutableLiveData()
// 设置初始值
init {
result.value = 0
}
// 通过 setValue() 更新值
fun add(number1: Int,number2:Int) {
result.value = number1 + number2
}
// 通过 getValue() 取值
fun getResult(): MutableLiveData<Int> {
/*
if (result.value==null){
result.value = 0
}*/
return result
}
}
Activity中使用
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: MainViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 创建ViewModel实例
viewModel = ViewModelProvider(this).get(MainViewModel::class.java)
// 设置初始化值,或SharedPreference的值
resultText.text = viewModel.getResult().toString();
val resultObserver:Observer<Int> = Observer<Int> {
result -> resultText.text = result.toString()
}
//观察LiveDada,
viewModel.getResult().observe(this, resultObserver)
// 求和
addBtn.setOnClickListener {
if(number1.text.isNotEmpty()&&number2.text.isNotEmpty()){
viewModel.add(number1.text.toString().toInt(),number2.text.toString().toInt())
}else{
resultText.text = "请正确输入"
}
}
}
}
PS: 关于LiveData的介绍就到这里。后续还有更深入的关于LiveData的扩展转换,和协程和Room的一起使用。敬请关注