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.
从官网的介绍可以看到,LiveData
作用跟RxJava
类似,是观察数据的类,相比RxJava
,它能够在Activity
、Fragment
和Service
之中正确的处理生命周期。 乍看之下,LiveData
挺鸡肋的,事实也确实如此,因为LiveData
能够实现的功能RxJava
也可以实现,而且与LiveData
相比, RxJava
拥有着更加丰富的生态,当然,谷歌的官方架构仍然值得我们去学习。
LiveData
是一种可观察的数据存储器类,它可以包含任何类型的数据。与常规的可观察类不同,LiveData
具有生命周期感知能力,意思是它遵循其它应用组件(如 Activity
、Fragment
或Service
)的生命周期。这种感知能力可确保LiveData
仅更新处于活跃生命周期状态的(应用组件)观察者。
如果观察者的生命周期处于STARTED
或RESUMED
状态,则LiveData
会认为该观察者处于活跃状态。LiveData
只会将更新通知给活跃的观察者,而非活跃观察者不会收到更改通知。 因此,可以在实现LifecycleOwner
接口的类中注册观察者,当相应的Lifecycle
对象的状态变为DESTROYED
时,便可移除此观察者。 这对于Activity
和Fragment
特别有用,这样它们就可以放心地观察LiveData
对象,而不必担心内存泄露(当Activity
和 Fragment
的生命周期结束时,系统会立即退订它们)。
使用LiveData
具有以下优势:
- 数据变更的时候更新
UI
。LiveData
遵循观察者模式,当数据发生变化时,LiveData
会通知Observer
对象,可以在这些Observer
对象中更新界面,无需在每次应用数据发生变化时更新界面,因为观察者会完成更新; - 不会发生内存泄漏。 观察者会绑定到
Lifecycle
对象,并在其关联的生命周期遭到销毁后进行自我清理; - 不会因
Activity
停止而导致崩溃。 如果观察者的生命周期处于非活跃状态(如返回栈中的Activity
),它不会接收任何LiveData
事件; - 不再需要手动处理生命周期。 界面组件只是观察相关数据,不会停止或恢复观察。
LiveData
将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化; - 数据始终保持最新状态。 如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的
Activity
会在返回前台后立即接收最新的数据; - 适当的配置更改。 如果由于配置更改(如设备旋转)而重新创建了
Activity
或Fragment
,它会立即接收最新的可用数据; - 共享资源。 可以使用单例模式扩展
LiveData
对象以封装系统服务,以便在应用中共享它们。LiveData
对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察LiveData
对象;
LiveData
经常与ViewModel
在一起使用,虽然它也可以单独用在别的地方,但是在绝大多数情况下,它是使用在ViewModel
当中的。
LiveData
和ViewModel
在整个MVVM
架构中担当数据驱动的职责,这也是MVVM
模式中ViewModel
层的作用。
为什么不把Activity
的实例传给ViewModel
呢,这样ViewModel
不就能主动对Activity
进行通知了吗?这是因为ViewModel
的生命周期是长于Activity
的,如果把Activity
的实例传给ViewModel
,就很有可能会因为Activity
无法释放而造成内存泄漏,这是一种非常错误的做法。
2 LiveData
的基本用法
- 创建
LiveData
的实例用来存储某种类型的数据,通常在ViewModel
类中完成; - 创建可定义
onChanged()
方法的Observer
对象,该方法可以控制LiveData
对象存储的数据更改时会发生什么。通常情况下,可以在界面控制器(如Activity
或Fragment
)中创建Observer
对象; - 使用
observe()
方法将Observer
对象附加到LiveData
对象,observe()
方法会采用LifecycleOwner
对象,这样会使Observer
对象订阅LiveData
对象,以使其收到有关更改的通知。通常情况下,可以在界面控制器(如Activity
或Fragment
)中附加Observer
对象;
注意:可以使用observeForever(Observer)
方法在没有关联的LifecycleOwner
对象的情况下注册一个观察者。在这种情况下,观察者会被视为始终处于活跃状态,因此它始终会收到关于修改的通知。可以通过调用removeObserver(Observer)
方法来移除观察者。
它的使用是首先使用LiveData
来存储某种类型的数据,这个过程一般是在ViewModel
中完成,之后创建Observer
对象,Observer
接口中只有一个方法onChange(T t)
,当数据发生变化时就会调用这个方法,一般是在组件,如Activity
/Fragment
中创建观察者对象;之后调用数据类的observe
方法,添加LifecycleOwner
对象和observer
,这样就可以观察数据的变化了。
当更新存储在 LiveData
对象中的值时,它会触发所有已注册的观察者(只要附加的 LifecycleOwner
处于活跃状态)。LiveData
允许界面控制器观察者订阅更新。当LiveData
对象存储的数据发生更改时,界面会自动更新以做出响应。
lifecycle-livedata-ktx
就是一个专门为Kotlin
语言设计的库,这个库在2.2.0
版本中加入了对observe()
方法的语法扩展。 我们只需要在app/build.gradle
文件中添加如下依赖:
dependencies {
...
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
}
2.1 创建LiveData
对象
LiveData
是一种可用于任何数据类型的封装容器,其中包括可实现 Collections
的对象,如List
。LiveData
对象通常存储在ViewModel
对象中,并可通过getter
方法进行访问, 如以下示例中所示:
class NameViewModel : ViewModel() {
// create a LiveData with a String
val currentName: MutableLiveData<String> by lazy {
MutableLiveData<String>()
}
// Rest of the ViewModel
}
注意:请确保用于更新界面的 LiveData
对象存储在 ViewModel
对象中,而不是将其存储在Activity
或Fragment
中,原因如下:避免 Activity
和Fragment
过于庞大。现在,这些界面控制器负责显示数据,但不负责存储数据状态。将 LiveData
实例与特定的Activity
或Fragment
实例分离开,并使 LiveData
对象在配置更改后继续存在。
LiveData
常用方法:
MutableLiveData
是一种可变的LiveData
,它的用法很简单,主要有3
种读写数据的方法,分别是getValue()
、setValue()
和postValue()
方法:
getValue()
方法用于获取LiveData
中包含的数据;setValue()
方法用于给LiveData
设置数据,但是只能在主线程中调用;postValue()
方法用于在非主线程中给LiveData
设置数据;
以下是MutableLiveData
和LiveData
的源码:
public class MutableLiveData<T> extends LiveData<T> {
public MutableLiveData(T value) {
super(value); }
public MutableLiveData() {
super(); }
@Override
public void postValue(T value) {
super.postValue(value); }
@Override
public void setValue(T value) {
super.setValue(value); }
}
public abstract class LiveData<T> {
}
2.2 观察LiveData
对象
在大多数情况下,应用组件的 onCreate()
方法是开始观察LiveData
对象的正确着手点,原因如下:
- 确保系统不会从
Activity
或Fragment
的onResume()
方法进行冗余调用; - 确保
Activity
或Fragment
变为活跃状态后具有可以立即显示的数据。一旦应用组件处于STARTED
状态,就会从它正在观察的LiveData
对象接收最新值。只有在设置了要观察的LiveData
对象时,才会发生这种情况;
通常,LiveData
仅在数据发生更改时才发送更新,并且仅发送给活跃观察者。此行为的一种例外情况是,观察者从非活跃状态更改为活跃状态时也会收到更新。此外,如果观察者第二次从非活跃状态更改为活跃状态,则只有在自上次变为活跃状态以来值发生了更改时,它才会收到更新。
以下示例代码说明了如何开始观察 LiveData
对象:
class NameActivity : AppCompatActivity() {
private val model: NameViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_name)
// Other code to setup the activity
// Create the observer which updates the UI.
val nameObserver = Observer<String> {
newName ->
// Update the UI, in this case, a TextView.
nameTextView.text = newName
}
// Observe the LiveData, passing in this activity as the LifecycleOwner and the observer
model.currentName.observe(this, nameObserver)
}
}
通过调用model.currentName.observe
方法来观察数据的变化。任何LiveData
对象都可以调用它的observe()
方法来观察数据的变化。observe()
方法接收两 个参数:第一个参数是一个LifecycleOwner
对象,Activity
本身就是一个LifecycleOwner
对象,因此直接传this
就好;第二个参数是一个Observer
接口, 当currentName
中包含的数据发生变化时,会立即调用Observer.onChanged
方法。
以下是Observer
的源码:
public interface Observer<T> {
void onChanged(T t);
}
另外,关于LiveData.observe()
方法,observe()
方法是一个Java
方法,如果观察Observer
接口,会发现这是一个单抽象方法接口,只有一个待实现的onChanged()
方法。因此也可以写成:
model.currentName.observe(this) {
newName ->
nameTextView.text = newName
}
2.3 更新 LiveData 对象
LiveData
没有公开可用的方法来更新存储的数据。MutableLiveData
类将公开setValue(T)
和postValue(T)
方法,如果需要修改存储在LiveData
对象中的值,则必须使用这些方法。通常情况下会在ViewModel
中使用 MutableLiveData
,然后 ViewModel
只会向观察者公开不可变的 LiveData
对象。
设置观察者关系后,可以更新 LiveData
对象的值(如以下示例中所示),这样当用户点按某个按钮时会触发所有观察者:
button.setOnClickListener {
val anotherName = "John Doe"
model.currentName.value = anotherName
}
在本示例中调用 setValue(T)
导致观察者使用值 John Doe
调用其onChanged()
方法。本示例中演示的是按下按钮的方法,但也可以出于各种各样的原因调用 setValue()
或 postValue()
来更新 mName
,这些原因包括响应网络请求或数据库加载完成。在所有情况下,调用 setValue()
或 postValue()
都会触发观察者并更新界面。
注意:必须调用setValue(T)
方法以从主线程更新 LiveData
对象。如果在工作器线程中执行代码,可以改用postValue(T)
方法来更新 LiveData
对象。
3 LiveData
的源码分析
3.1 LiveData.observe(LifecyleOwner owner, Observer<? super T> observer)
在obsever
方法中传入了两个参数,一个是LifecycleOwner
,一个是Observer
。**Observer
是观察者,它是一个单一方法接口,当数据发生变化时,会回调onChange(T t)
方法,**以下是相关源码:
public interface Observer<T> {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(T t);
}
之后来看observe
方法的具体实现,以下是源码:
public abstract class LiveData<T> {
private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers = new SafeIterableMap<>();
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
// 1. 只能在主线程中调用observe方法
assertMainThread("observe");
// 2. 当Lifecycle.State == DESTROYED时,订阅观察者时没有意义的,直接返回
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
// 3. LifeycleBoundObserver最终是LifecycleObserver的实现类
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
// 4. observer作为key,wrap