LiveData
是一种具有感知应用组件(Activity
、Fragment
、Service
)生命周期的,可观察的数据存储器类。这种感知能力可确保LiveData
仅更新处于活跃生命周期状态的应用组件观察者。(官网解释)
LiveData的使用
先附上一张demo效果图
在使用LiveData
前,需要先添加依赖。
LiveData
的依赖,可以查看官方文档,导入最新的版本。
现在示例使用的版本:
def lifecycle_version = "2.2.0"
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
创建 LivaData 对象
LiveData
是一个数据的封装容器,可以存放包括实现了Collection
的对象,如List
。
LiveData
对象通常存储在ViewModel
中,可以通过getter
进行访问,通过setter
修改(异步需要用postValue
)。
ViewModel
可以参考上一篇文章,Android Jetpack — ViewModel
class NumberViewModel : ViewModel() {
val num: MutableLiveData<Int> by lazy {
MutableLiveData<Int>(0)
}
}
添加 LivaData 监听
//获取ViewModel
mViewModel = ViewModelProvider(this).get(NumberViewModel::class.java)
//新建一个观察者
val numObserver = Observer<Int> { num ->
mTvNum.text = num.toString()
}
//开始监听
mViewModel.num.observe(this, numObserver)
监听时机:通常是在Activity
或Fragment
的oncreate
中,这样的好处是当组件处于STARTED
状态时,就能接收到LiveData
对象的最新数据。同时,也能确保在onResult
中的重复调用。
接收到数据更新的时机:
- 数据发生更改
- 观察者从非活跃状态更改为活跃状态
- 观察者第二次从非活跃状态更改为活跃状态,只有在自上次变为活跃状态以来数据发生了更改时,才会收到更新
注意:如果
LiveData
对象num
中设置了初始值,则在调用了observe()
后,会立即掉用onChange()
; 如果未设置初始值,则不会调用。
更新数据
mBtnAdd.setOnClickListener {
//java mViewModel.num.setValue(mViewModel.num.value as Int + 1)
mViewModel.num.value = mViewModel.num.value as Int + 1
}
更新LiveData
数据需要调用MutableLiveData
类的setValue(T)
或者postValue(T)
方法,LiveData
类的这两个方法是不公开的。
而setValue(T)
和postValue(T)
两者是有区别的:
setValue(T)
只能在主线程调用,而postValue(T)
可以在子线程调用。
/**
* Posts a task to a main thread to set the given value. So if you have a following code
* executed in the main thread:
* <pre class="prettyprint">
* liveData.postValue("a");
* liveData.setValue("b");
* </pre>
* The value "b" would be set at first and later the main thread would override it with
* the value "a".
* <p>
* If you called this method multiple times before a main thread executed a posted task, only
* the last value would be dispatched.
*
* @param value The new value
*/
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
/**
* Sets the value. If there are active observers, the value will be dispatched to them.
* <p>
* This method must be called from the main thread. If you need set a value from a background
* thread, you can use {@link #postValue(Object)}
*
* @param value The new value
*/
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
通过源码可以看出,当调用postValue
之后,会把任务抛到主线程中去执行,而setValue
是直接执行。
需要注意的是,如果在主线程中执行以下代码:
liveData.postValue("a");
liveData.setValue("b");
会先把value
设置为b
,然后a
覆盖b
的值。
扩展
liveData
还可以和Room
、协程等一起使用,还有很多高级的用法,后续继续记录。