一、前言
1、什么是 LiveData
LiveData
是一个数据持有类。它具有以下特点:
- 数据可以被 观察者 订阅;
- 能够感知组件( Fragment、Activity、Service ) 的生命周期;
- 只有在 组件 处于 激活状态才会通知观察者有数据更新;
2、LiveData 能为我们做什么
-
能够保证 数据 和
UI
统一。LiveData
采用了 观察者模式,LiveData
是被观察者,当数据有变化时会通知UI
。 -
减少内存泄露。
LiveData
能够感知到组件的生命周期,当组件处于 销毁(destroyed
) 状态时,观察者对象会被清除,当Activity
停止时不会导致crash
,因为 组件处于非激活状态时,不会收到LiveData
中数据变化的通知。 -
组件和数据相关的内容能够实时更新。组件在前台的时候能够实时收到数据改变的通知,当组件从后台切换到前台时,
LiveData
能够将最新的数据通知组件,因此保证了组件中和数据相关的内容能够实时更新。 -
解决横竖屏切换(
configuration change
)数据问题。在屏幕发生旋转时,不需要额外的处理来保存数据,当屏幕方向变化时,组件会被recreate
,然而系统并不能保证你的数据能够被恢复。当采用LiveData
保存数据时,因为数据和组件分离了,当组件被recreate
,数据还是存在LiveData
中,并不会被销毁。 -
资源共享。如果对应的
LiveData
是单例的话,就能在App
的组件间分享数据;这部分详细的信息可以参考 继承LiveData
。
二、简单使用
1、创建LiveData
LiveData
的2种创建方式:
- 直接使用
MutableLiveData
对象; - 自行继承
LiveData
类。
1.1、直接使用 MutableLiveData
MutableLiveData<String> data = new MutableLiveData<>();
1.2、继承 LiveData
2、创建并订阅观察者
LiveData
通过 observe()
方法注册观察者。观察者这里使用匿名方式:
// 写于MainActivity
data.observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show();
}
});
Observe() 源码分析:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
observe
方法接收 2
个参数:
- 一个是具有生命周期的
LifecycleOwner
; - 另一个是观察者
Observer<T>
.
首先判断 LifecycleOwner
当前的生命周期是否为 Destroyed
:
- 如果是则直接
return
; - 如果不等于
Destroyed
,new
了一个内部类LifecycleBoundObserver
对象并且构造方法传入了具有生命周期的LifecycleOwner
和 观察者。看下源码:
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
LifecycleBoundObserver
继承自 ObserverWrapper
,并实现 GenericLifecycleObserver
,而 GenericLifecycleObserver
继承了 LifecycleObserver
接口。
由此可以看出LifecycleBoundObserver
类就是把Observer
和生命周期关联起来。
再看此类,我们先看 onStateChanged()
方法,当生命周期变化时会回调,如果getCurrentState() == DESTROYED
则 removeObserver
,反之则调用父类ObserverWrapper
的activeStateChanged()
方法:
private abstract class ObserverWrapper {
final Observer<T> mObserver;
boolean mActive;
int mLastVersion = START_VERSION;
ObserverWrapper(Observer<T> observer) {
mObserver = observer;
}
abstract boolean shouldBeActive();
boolean isAttachedTo(LifecycleOwner owner) {
return false;
}
void detachObserver() {
}
void activeStateChanged(boolean newActive) {
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
}
分析activeStateChanged()
:
-
首先判断
activeState
新旧状态是否相同,不同则把新的状态赋给mActive
,是生命周期状态处于ACTIVE
情况下的逻辑处理。如果新的状态和旧的状态相同则直接返回。 -
这里有个常量
LiveData.this.mActiveCount
,看注释可以理解为观察者处于活动状态 个数。 -
往下看
if (wasInactive && mActive)
。 如果mActiveCount=0
并且mActive
为true
,即观察者处于活动状态。- 个数从
0
变为1
个则调用onActive()
; 观察者处于活动状态 - 个数从
1
变为0
时则调用onInactive()
- 个数从
然而onActive()
,onInactive()
并没有任何实现代码。好了,接下来继续往下看dispatchingValue(this);
应该就是数据变化消息调度。源代码:
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
前面的几行if 判断姑且先不看,先看从if(initiator != null)
开始看,如果initiator!= null
调用considerNotify(initiator)
方法;源代码:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
最后一行代码 observer.mObserver.onChanged((T) mData);
Observer
的数据变化回调;
好了我们再回过头看看initiator == null
的逻辑:
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
如果initiator == null
则会通过迭代器mObservers
遍历获取 ObserverWrapper
,最终还是调用 considerNotify
方法;既然有取 ObserverWrapper
,咋们再看看在哪儿存的:
回到 Observe() 方法中:
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addObserver(wrapper);
}
mObservers.putIfAbsent(observer, wrapper)
存入容器中,mObservers.putIfAbsent
这个添加数据的方式貌似很少见,于是乎在看看 mObservers
是个什么数据容器,成员变量中:
private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers =
new SafeIterableMap<>();
SafeIterableMap
有以下特性:
- 支持键值对存储,用链表实现,模拟成
Map
的接口 - 支持在遍历的过程中删除任意元素,不会触发
ConcurrentModifiedException
- 非线程安全
最后 addObserver
添加注册。
3、发起数据通知
发起数据通知 2 种方式:
postValue
setValue
data.postValue("Hello LiveData");
// data.setValue("Hello 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);
}
}
我们先看看setValue
代码:
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
private static void assertMainThread(String methodName) {
if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
}
assertMainThread("setValue");
则是判断是否在主线程。
所以貌似**setValue
方式必须在主线程中执行,如果非主线程则抛出异常。 **
再看看postValue
:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
则postValue
调用postToMainThread
方法,最终还是用过setValue
方式:
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
};
因此最终明白为什么 setValue
方法只能在主线程中调用,postValue
可以在任何线程中调用,如果是在后台子线程中更新 LiveData
的值,必须调用postValue
。
三、高级应用
1、 LiveDataBus
的设计和架构
LiveDataBus
的组成
-
消息 消息可以是任何的
Object
,可以定义不同类型的消息,如Boolean
、String
。也可以定义自定义类型的消息。 -
消息通道
LiveData
扮演了消息通道的角色,不同的消息通道用不同的名字区分,名字是String
类型的,可以通过名字获取到一个LiveData
消息通道。 -
消息总线
消息总线通过单例实现,不同的消息通道存放在一个HashMap
中。 -
订阅
订阅者通过getChannel
获取消息通道,然后调用observe
订阅这个通道的消息。 -
发布
发布者通过getChannel
获取消息通道,然后调用setValue
或者postValue
发布消息。
来源:oschina
链接:https://my.oschina.net/u/3739435/blog/3121608