概述
LiveData 是一个可被观察的数据持有类。与普通的被观察者(如 RxJava 中的 Observable)不同的是,LiveData 是具有生命周期感知的,简单的说,它能感知其它应用组件(Activity,Fragment,Service)的生命周期。这种感知能力可以确保只有处于 active 状态的组件才能收到 LiveData 的更新。
优势
能够保证数据和UI统一
LiveData采用了观察者模式,LiveData是被观察者,当数据有变化时会通知UI。降低内存泄漏
LiveData能够感知到组件的生命周期,当组件处于DESTROYED状态时,观察者对象会被清除,当Activity停止时不会导致Crash,因为组件处于非激活状态时,不会收到LiveData中数据变化的通知。不需要额外的手动处理来响应生命周期的变化
因为LiveData能够感知组件的生命周期,所以就完全不需要在代码中告诉LiveData组件的生命周期状态。组件和数据相关的内容能实时更新
组件在前台的时候能够实时收到数据改变的通知,当组件从后台到前台来时,LiveData能够将最新的数据通知组件,因此保证了组件中和数据相关的内容能够实时更新。资源共享
源码分析
众所周知在MVVM设计模式中,LiveData被我们广泛使用,那么它是如何做到数据绑定和数据更新的呢,除了MutableLiveData还有其他用法吗?随着我的脚步一起看看吧!
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);
}
}
从源码中我们可以看到MutableLiveData提供了setValue和postValue方式添加数据,那么他们有何区别呢?
MutableLiveData. 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");
}
}
从上述@MainThread和assertMainThread()方法中,我们得出setValue的方法有且仅能在主线程中使用。
MutableLiveData. postValue
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
···
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
//noinspection unchecked
setValue((T) newValue);
}
}
postValue最终调用postToMainThread(mPostValueRunnable),而mPostValueRunnable中run方法最终调用的是setValue(),因此我们可以得出postValue可以在任何线程中使用。
MediatorLiveData
LiveData liveData1 = ...;
liveDataMerger.addSource(liveData1, new Observer() {
private int count = 1;
@Override public void onChanged(@Nullable Integer s) {
count++;
liveDataMerger.setValue(s);
if (count > 10) {
liveDataMerger.removeSource(liveData1);
}
}
});
由图可知MediatorLiveData是继承MutableLiveData,它是用addSource对LiveData数据进行处理。
@MainThread
public <S> void addSource(LiveData<S> source, Observer<S> onChanged) {
//新建一个Source并且将该Source的Observer传进去
Source<S> e = new Source<>(source, onChanged);
//检查这个Source是否存在
Source<?> existing = mSources.putIfAbsent(source, e);
//如果存在且这个Source的Observer不等于新传进来的Observer就会报错
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {//如果存在直接return
return;
}
if (hasActiveObservers()) {//不存在就插入(plug)
e.plug();
}
}
void plug() {
mLiveData.observeForever(mObserver);
//observeForever()这个方法不会自动移除,需要手动停止实际它内部调用的是observe(ALWAYS_ON, observer);
}
void unplug() {
mLiveData.removeObserver(mObserver);
//主线程中移除
}
从源代码中可以看出addSource传入的是LiveData和Observer,那么什么时候Observer中onChanged回调呢,下面代码中可以看出,MediatorLiveData处于active时Observer的onChange()才会回调。
protected void onActive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().plug();
}
}
protected void onInactive() {
for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
source.getValue().unplug();
}
}
Transformations
Transformations类中有两个方法分别是switchMap和map,内部使用MediatorLiveData.addSource(),此处我就不做详述。
val userLiveData: LiveData<User> = UserLiveData()
val userName: LiveData<String> = Transformations.map(userLiveData) {
user -> "${user.name} ${user.lastName}"
}
map操作在LiveData数据的改变传递到观察者之前,对数据或者View进行处理。
private fun getUser(id: String): LiveData<User> {
...
}
val userId: LiveData<String> = ...
val user = Transformations.switchMap(userId) { id -> getUser(id) }
与Transformations.map()类似,只不过这里传递个switchMap()的方法必须返回一个LiveData对象。
LiveData实现RxBus效果
public final class LiveDataBus {
private final Map<String, BusMutableLiveData<Object>> bus;
private LiveDataBus() {
bus = new HashMap<>();
}
private static class SingletonHolder {
private static final LiveDataBus DEFAULT_BUS = new LiveDataBus();
}
public static LiveDataBus get() {
return SingletonHolder.DEFAULT_BUS;
}
public <T> MutableLiveData<T> with(String key, Class<T> type) {
if (!bus.containsKey(key)) {
bus.put(key, new BusMutableLiveData<>());
}
return (MutableLiveData<T>) bus.get(key);
}
public MutableLiveData<Object> with(String key) {
return with(key, Object.class);
}
private static class ObserverWrapper<T> implements Observer<T> {
private Observer<T> observer;
public ObserverWrapper(Observer<T> observer) {
this.observer = observer;
}
@Override
public void onChanged(@Nullable T t) {
if (observer != null) {
if (isCallOnObserve()) {
return;
}
observer.onChanged(t);
}
}
private boolean isCallOnObserve() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if (stackTrace != null && stackTrace.length > 0) {
for (StackTraceElement element : stackTrace) {
if ("android.arch.lifecycle.LiveData".equals(element.getClassName()) &&
"observeForever".equals(element.getMethodName())) {
return true;
}
}
}
return false;
}
}
private static class BusMutableLiveData<T> extends MutableLiveData<T> {
private Map<Observer, Observer> observerMap = new HashMap<>();
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
super.observe(owner, observer);
try {
hook(observer);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void observeForever(@NonNull Observer<T> observer) {
if (!observerMap.containsKey(observer)) {
observerMap.put(observer, new ObserverWrapper(observer));
}
super.observeForever(observerMap.get(observer));
}
@Override
public void removeObserver(@NonNull Observer<T> observer) {
Observer realObserver = null;
if (observerMap.containsKey(observer)) {
realObserver = observerMap.remove(observer);
} else {
realObserver = observer;
}
super.removeObserver(realObserver);
}
private void hook(@NonNull Observer<T> observer) throws Exception {
//get wrapper's version
Class<LiveData> classLiveData = LiveData.class;
Field fieldObservers = classLiveData.getDeclaredField("mObservers");
fieldObservers.setAccessible(true);
Object objectObservers = fieldObservers.get(this);
Class<?> classObservers = objectObservers.getClass();
Method methodGet = classObservers.getDeclaredMethod("get", Object.class);
methodGet.setAccessible(true);
Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
Object objectWrapper = null;
if (objectWrapperEntry instanceof Map.Entry) {
objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
}
if (objectWrapper == null) {
throw new NullPointerException("Wrapper can not be bull!");
}
Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
fieldLastVersion.setAccessible(true);
//get livedata's version
Field fieldVersion = classLiveData.getDeclaredField("mVersion");
fieldVersion.setAccessible(true);
Object objectVersion = fieldVersion.get(this);
//set wrapper's version
fieldLastVersion.set(objectWrapper, objectVersion);
}
}
}
上述借鉴美团技术博客的事件总线实现方案,链接如下:
LiveEventBus