简介
LiveData
是一种可观察的数据存储器类。与常规的可观察类不同,LiveData具有生命周期感知能力,即遵循其他引用组件(如Activity,Fragment或Service)的生命周期。这可以保证LiveData仅更新处于活跃生命周期状态的应用组件观察者,例如观察者的生命周期处于STARTED
或RESUMED
状态,则LiveData会认为该观察者处于活跃状态,只会将更新通知给活跃状态的观察者,非活跃观察者不会收到更改通知。
LiveData的简单使用
- 创建LiveData实例以存储某种类型的数据,一般LiveData的初始化在ViewModel中完成。
val data:MutableLiveData by lazy {
MutableLiveData()
}
- 创建可定义onChanged()方法的Observe对象,onChanged()在LiveData对象存储的数据发生改变时调用。
- 使用observe()方法将定义的Observer对象附加到LiveData对象上,这就是我们所说的订阅。
mViewModel.cityData.observe(this, {
//数据发生改变的时候,执行到这里,可以做相应的处理
})
更新LiveData对象数
MutableLiveData
类通过公开setValue(T)和postValue(T)方法进行更新,其中setValue(T)方法只能在主线程中使用,如果在工作线程需要用到postValue(T)方法来更新LiveData对象。
cityData.value = tempStr
使用LiveData的优点
- 确保界面符合数据状态
- 不会发生内存泄露
观察者会绑定到Lifecycle对象,并在其关联的生命周期遭到销毁后进行自我清理。
- 不会因Activity停止而导致崩溃
如果观察者的生命周期处于非活跃状态,则不会收到任何LiveData事件。
- 不需要手动处理生命周期。
界面组件只需要观察相关数据,不会停止或恢复观察,LiveData将自动管理所有这些操作。
数据始终保持最新状态。
适应配置更改
如果因为配置发生改变,而重新创建了Activity或Fragment,它会立即接收到最新的可用数据。
- 共享资源
LiveData的源码分析
public abstract class LiveData
LiveData是一个抽象类,不能直接实例化。我们可以使用它的子类MutableLiveData
public class MutableLiveData extends LiveData {
//在工作线程中使用
@Override
public void postValue(T value) {
super.postValue(value);
}
//在主线程中使用
@Override
public void setValue(T value) {
super.setValue(value);
}
}
MutableLiveData提供了postValue()
和setValue()
两个方法,给使用者用来更新数据。这两个方法最后都是分别调用了父类的对应方法,并不没有做什么特别的处理,只是进行了封装。
当初始化实例之后,我么可以通过observe()
或者observeForever()
方法进行注册。
observeForever()
和observe()
的区别在于,使用observeForever()
无论何时,只要数据更新,观察者将收到所有事件,并且永远不会自动删除,需要手动调用removeObserver(Observer)
进行移除。而observe()
只有在活跃的状态才会接收到。
接下来我们重点分析一下observe()
方法:
-
observe()方法
在调用observe()需要传入一个Observer的参数,这是一个回调接口,当时数据发生变动的时候,就会回调用onChanged()方法。
public interface Observer {
/**
* Called when the data is changed.
* @param t The new data
*/
void onChanged(T t);
}
observer()方法实现的流程:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) {
//用于判断是否在主线程,说明该方法的调用需要在主线程中调用
assertMainThread("observe");
//当前组件状态处于销毁状态的时候,直接返回。(observeForever是没有这个处理逻辑的)
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
//实例化一个LifecycleBoundObserver的对象
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//通过健值对的方式进行存储,如果之前没有存储过的则返回为null,如果已经存储过则不为null
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//判断是否已经添加过了同一个LifecycleOwner
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
//不为空,说明已经添加过了,直接返回
if (existing != null) {
return;
}
//添加一个wrapper,与组件的生命周期发生联系。当生命周期发生改变的时候
//就回去回调wrapper中的onStateChanged
owner.getLifecycle().addObserver(wrapper);
}
在该流程中,可以看到,observer()
与组件的生命周期绑定,需要 LifecycleBoundObserver
的这个类。接下来对该类进行分析:
-
LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer super T> observer) {
super(observer);
mOwner = owner;
}
//重写ObserverWrapper的方法,返回当前的组件是否是活跃的状态(STARTED和RESUMED)
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//当组件生命周期发生变化的时候,回调该方法
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//判断组件的生命周期状态是否是DESTROYED
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
//如果是DESTROYED,则移除观察者。
removeObserver(mObserver);
return;
}
//调用ObserverWrapper的方法
activeStateChanged(shouldBeActive());
}
//重写ObserverWrapper的方法,判断是不是同一个生命周期
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
//移除当前的对象
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
LifecycleBoundObserver
实现了GenericLifecycleObserver
的回调接口,该接口主要用来监听组件生命周期的变化,当组件生命周期发生变化的时候,会回调onStateChanged()
的方法。该类还继承了ObserverWrapper
。接下来我们继续看看ObserverWrapper
-
ObserverWrapper
private abstract class ObserverWrapper {
final Observer super T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer super T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
//判断状态是否改变,没有则返回
if (newActive == mActive) {
return;
}
//立即设置为活动状态,因此我们永远不会将任何内容分派到不活动状态
//设置新的状态
mActive = newActive;
//判断当前观察者数量是否为0
boolean wasInactive = LiveData.this.mActiveCount == 0;
//如果该组件时活跃的,则mActive+1,否则-1
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
//当活跃观察者的数量从0变为1时调用
//空方法
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
//当活跃的观察者的数量从1变为0时调用
//空方法
onInactive();
}
//当组件活跃的时候调用dispatchingValue
if (mActive) {
//这个方法最终会调用considerNotify方法更新数据
dispatchingValue(this);
}
}
}
从上面的流程看到当组件的生命周期发生变动的时候,当组件处于活跃状态的时候会通过dispatchingValue()方法
调用到considerNotify(ObserverWrapper observer)
-
considerNotify(ObserverWrapper observer)
private void considerNotify(ObserverWrapper observer) {
//如果组件处于非活跃的状态,则直接返回
if (!observer.mActive) {
return;
}
//继续判断是否处于活跃状态,如果不是,则更新状态并且返回
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//用于判断数据是否更新,因为当调用setValue时mVersion会加1
//没有更新直接返回
if (observer.mLastVersion >= mVersion) {
return;
}
//更新mLastVersion的值
observer.mLastVersion = mVersion;
//noinspection unchecked
//将数据传给onChange(),会触发接口回调。
observer.mObserver.onChanged((T) mData);
}
该方法会调用onChange()
方法,而这个方法的实体就是我们在使用的时候创建的Observer()
的onChange()
方法。可以看到这个方法的触发需要满足两个条件:当前的组件处于活跃的状态;数据发生更新;判断数据是否发生更新时通过设置一个计算器 mVersion
,在更新数据的时候,进行+1,然后与mLastVersion
值进行判断。
-
setValue(T value)
@MainThread
protected void setValue(T value) {
//判断是否是在主线程调用
assertMainThread("setValue");
//将 mVersion++;
mVersion++;
//更新值
mData = value;
//调用该方法,最后会通知观察者进行数据的更新
dispatchingValue(null);
}
//在工作线程中设置值
//将任务发布到主线程以设置给定值
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
//将任务post到主线程
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//最后还是通过setValue()设置新的值
setValue((T) newValue);
}
};
虽然postValue()
是在工作线程中使用,但是最后还是将任务发送给主线程,然后调用setValue()
的方法进行值的更新操作。如果在主线中执行了下面的代码:
liveData.postValue("a");
liveData.setValue("b");
首先将设置值“ b”,然后主线程将使用值“ a”覆盖它。如果在主线程执行发布的任务之前多次调用此方法,则只会分派最后一个值。
以上是LiveData的使用和简单的源码分析。
参考:
https://blog.csdn.net/cs_lwb/article/details/103041866