在 LiveData 出现之前,一般状态分发我们使用EventBus或者RxJava,这些都很容易出现内存泄漏问题,而且需要我们手动管理生命周期。而 LiveData 则规避了这些问题,LiveData 是一个持有 Activity、Fragment 生命周期的数据容器。当数据源发生变化的时候,通知它的观察者更新 UI 界面。同时它可以只通知处于 Active 状态的观察者更新界面。所以不用担心内存泄漏问题。一般来说,LiveData很少单独使用,它更多的和Android Jetpack的其他组件搭配使用,比如和ViewModel。这篇文章就来介绍LiveData的使用。
LiveData 是一个可观察的数据持有者,和常规的observable不同,LiveData 是可以感知生命周期的,也就是说它能够在 Activity、Fragment、Service 中正确的处理生命周期。
LiveData 的数据源一般是 ViewModel,也可以是其它可以更新 LiveData 的组件。当数据更新后,LiveData 就会通知它的所有观察者,比如 Activity。与 RxJava 的方法不同的是,LiveData 可以不通知所有观察者,它可以只通知处于 Active 状态的观察者。这对于Activity 和 Service 特别有用,因为它们可以安全地观察 LiveData 对象而不用担心内存泄漏的问题。还有一点需要注意的是一旦观察者重新恢复到活跃状态,它将会重新收到 LiveData 的最新数据。
LiveData 是一个抽象类,它的最简单的实现类为 MutableLiveData,使用方法如下所示:
public class MainActivity extends AppCompatActivity { MutableLiveDatamutableLiveData = new MutableLiveData<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mutableLiveData.observe(this, new Observer () { @Override public void onChanged(@Nullable final String s) { Log.d("MainActivity", "onChanged:"+s); } }); mutableLiveData.postValue("LiveData 基本使用"); } }
MutableLiveData 的 observe 方法有两个参数分别是 LifecycleOwner 和 Observer
,第一个参数就是MainActivity 本身,第二个参数新建了一个Observer
,在onChanged方法中得到回调。postValue 方法会在主线程中更新数据,运行结果如下所示:
除了 MutableLiveData 的 postValue 方法,还可以使用 setValue 方法,它们之前的区别是,setValue 方法必须在主线程使用,如果是在子线程线程中更新 LiveData,则可以使用 postValue 方法。
如果我们想要在 LiveData 对象分发给观察者之前对其中存储的值进行更改,可以使用 Transformations.map() 和Transformations.switchMap(),下面通过简单的例子来讲解它们。
如果想要在 LiveData 对象分发给观察者之前对其中存储的值进行更改,可以使用Transformations.map()。
public class MainActivity extends AppCompatActivity { MutableLiveDatamutableLiveData = new MutableLiveData<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mutableLiveData.observe(this, new Observer () { @Override public void onChanged(@Nullable final String s) { Log.d("MainActivity", "onChanged:"+s); } }); LiveData transformedLiveData = Transformations.map(mutableLiveData, new Function () { @Override public Object apply(String name) { return name + " + Transformations.map 的使用"; } }); transformedLiveData.observe(this, new Observer() { @Override public void onChanged(@Nullable Object o) { Log.d("MainActivity", "onChanged2:"+o.toString()); } }); mutableLiveData.postValue("LiveData 基本使用"); } }
通过Transformations.map(),在mutableLiveData的基础上又加上了字符串" + Transformations.map 的使用"。
运行结果如下所示:
public class MainActivity extends AppCompatActivity { private MutableLiveDatamutableLiveData1; private MutableLiveData mutableLiveData2; private MutableLiveData liveDataSwitch; private LiveData transformedLiveData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mutableLiveData1 = new MutableLiveData<>(); mutableLiveData2 = new MutableLiveData<>(); liveDataSwitch = new MutableLiveData<>(); transformedLiveData= Transformations.switchMap(liveDataSwitch, new Function >() { @Override public LiveData apply(Boolean input) { if (input) { return mutableLiveData1; } else { return mutableLiveData2; } } }); transformedLiveData.observe(this, new Observer () { @Override public void onChanged(@Nullable final String s) { Log.d("MainActivity", "onChanged:" + s); } }); liveDataSwitch.postValue(false); mutableLiveData1.postValue("Transformations.switchMap 用法1"); mutableLiveData2.postValue("Transformations.switchMap 用法2"); } }
MutableLiveData
用来控制切换,当 liveDataSwitch 的值为true时返回mutableLiveData1,否则返回 mutableLiveData2。
MediatorLiveData 继承自 mutableLiveData,它可以将多个 LiveData 数据源集合起来,可以达到一个组件监听多个 LiveData 数据变化的目的,用法如下所示:
public class MainActivity extends AppCompatActivity { private MutableLiveDatamutableLiveData1; private MutableLiveData mutableLiveData2; private MediatorLiveData mediatorLiveData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mutableLiveData1 = new MutableLiveData<>(); mutableLiveData2 = new MutableLiveData<>(); mediatorLiveData = new MediatorLiveData (); mediatorLiveData.addSource(mutableLiveData1, new Observer() { @Override public void onChanged(@Nullable Object o) { Log.d("MainActivity", "onChanged1:" + o.toString()); } }); mediatorLiveData.addSource(mutableLiveData2, new Observer() { @Override public void onChanged(@Nullable Object o) { Log.d("MainActivity", "onChanged2:" + o.toString()); } }); mediatorLiveData.observe(this, new Observer() { @Override public void onChanged(@Nullable Object o) { Log.d("MainActivity", "onChanged:" + o.toString()); } }); mutableLiveData1.postValue("mutableLiveData 1"); mutableLiveData2.postValue("mutableLiveData 2"); mediatorLiveData.postValue("mediatorLiveData 使用"); } }
通过 MediatorLiveData 的 addSource 将两个 MutableLiveData 合并到一起,这样当任何一个 MutableLiveData数据发生变化时,MediatorLiveData 都可以感知到,运行结果如下所示:
由于 LiveData 是一个 abstract class,我们不能直接生成他的实例。官方有提供他的实现类MutableLiveData
,代码如下所示:
public class MutableLiveDataextends LiveData { ... // 可以在子线程中调用 @Override public void postValue(T value) { super.postValue(value); } // 必须在主线程中调用 @Override public void setValue(T value) { super.setValue(value); } }
创建了 LiveData 后,需要通过 observe 方法或者 observeForever 方法设置一个观察者,这个观察者接口就是Observer,代码如下:
public interface Observer{ // 这个回调发生在主线程 void onChanged(T t); }
LiveData 的添加观察者的代码如下:
public abstract class LiveData{ ... // 只有onStart之后,onStop之前,对数据的修改才会触发 observer.onChanged() public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) { } // 无论何时,只要数据发生改变,就会触发 observer.onChanged() public void observeForever(@NonNull Observer super T> observer) { } ... }
observeForever 的实现跟 observe 是类似的,这里我们重点看一下 observe()的实现过程,代码如下:
// 只能在主线程调用 @MainThread public void observe(@NonNull LifecycleOwner owner, @NonNull Observer super T> observer) { assertMainThread("observe"); //如当前UI的状态的是DESTROYED,就不绑定这个回调了 if (owner.getLifecycle().getCurrentState() == DESTROYED) { // ignore return; } //创建生命周期感知的观察者包装类(把注册进来的observer包装成一个具有生命周边边界的观察者) LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer); //接着会判断该观察是否已经注册过了,如果是则抛异常, 对应观察者只能与一个owner绑定,不允许重复注册 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; } //把wrapper与Activity/Fragment的生命周期,建立关系, //当UI的生命周期发生变化的时候,就会去回调wrapper中的onStateChanged方法 owner.getLifecycle().addObserver(wrapper); }
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer super T> observer) { super(observer); mOwner = owner; } @Override boolean shouldBeActive() { /* 观察者是否活跃就等于mOwner的状态是否大于等于STARTED; 如果页面当前不可见,你发送了一条消息,此时是不会被分发的, 可以避免后台任务抢占资源,当页面恢复可见才会分发。 */ return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } // Activity/Fragment的生命周期变化会回调此方法。 @Override public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) { Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState(); // 如果当接收到DESTROYED的事件会自动解除跟owner的绑定,避免内存泄露 if (currentState == DESTROYED) { removeObserver(mObserver); return; } Lifecycle.State prevState = null; while (prevState != currentState) { prevState = currentState; //说明宿主的状态发生了变化,此时会判断宿主是否处于活跃状态 activeStateChanged(shouldBeActive()); currentState = mOwner.getLifecycle().getCurrentState(); } } @Override boolean isAttachedTo(LifecycleOwner owner) { return mOwner == owner; } @Override void detachObserver() { mOwner.getLifecycle().removeObserver(this); } }
状态变更后,如果观察者处于活跃状态会触发数据的分发流程
private abstract class ObserverWrapper { final Observer super T> mObserver; boolean mActive; //ObserverWrapper在每次注册的时候都会重新new,所以mLastVersion每次都是-1开始。 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; } // immediately set active state, so we'd never dispatch anything to inactive // owner mActive = newActive; // 更新活跃值 活跃1 非活跃-1 changeActiveCounter(mActive ? 1 : -1); if (mActive) { // 如果是活跃状态,分发值 dispatchingValue(this); } } }
changeActiveCounter 方法代码如下:
@MainThread void changeActiveCounter(int change) { // 上一次的活跃数 int previousActiveCount = mActiveCount; // 当前活跃数 mActiveCount += change; if (mChangingActiveState) { return; } mChangingActiveState = true; try { while (previousActiveCount != mActiveCount) { // 从不活跃变为活跃状态,需要回调 onActive方法 boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0; // 从活跃状态变为不活跃状体,需要回调onInactive方法 boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0; previousActiveCount = mActiveCount; if (needToCallActive) { onActive(); } else if (needToCallInactive) { onInactive(); } } } finally { mChangingActiveState = false; } }
dispatchingValue(this)数据分发流程控制:(内部执行considerNotify(initiator)方法),这个方法我们后面分析。
postValue 最终也是调用 setValue 方法,这里就不做分析了,我们主要分析 setValue 方法,代码如下:
@MainThread protected void setValue(T value) { assertMainThread("setValue"); // 这个mVersion是属于LiveData的,然后只在setValue // (postValue最终也会调用setValue)的时候会自增1 mVersion++; // 保存这次变化的数据 mData = value; // 分发数据 dispatchingValue(null); }
接下来我们具体分析 dispatchingValue 方法,代码如下:
@SuppressWarnings("WeakerAccess") /* synthetic access */ void dispatchingValue(@Nullable ObserverWrapper initiator) { if (mDispatchingValue) { mDispatchInvalidated = true; return; } //进入while循环前,设置为true,如果此时另外一个数据发生变化,到了此函数中就直接在上面返回了 mDispatchingValue = true; do { //开始for循环前,设置为false,for循环完,也会退出while循环 mDispatchInvalidated = false; if (initiator != null) { // 如果传递的观察者不为空,则把数据分发给他自己。 // 这个流程是Activity/Fragment的生命周期发生变化的时候会被触发 considerNotify(initiator); initiator = null; } else { // 遍历集合中所有已注册的的观察者,逐个调用considerNotify,分发数据 for (Iterator, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); //这里mDispatchInvalidated 为true,表示在while循环未结束的时候, // 有其他数据发生变化,并调用了该函数 //在上面的if判断中设置了 mDispatchInvalidated = true, // 结束本次for循环,没有退出while循环,开始下一次for循环 if (mDispatchInvalidated) { break; } } } } while (mDispatchInvalidated); //退出while 后,设置为false,正常处理数据变化 mDispatchingValue = false; }
这里有两个变量
mDispatchingValue 这个变量用来控制,是否进入while 循环,以及while 循环 是否已经结束
mDispatchInvalidated 这个变量用来控制for 循环是否要重新开始
看下considerNotify 的函数,调用了之前 LiveData 设置的 observer 的 onChanged 函数,代码如下:
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. // 如果当前的生命周期是非活跃,就不回调onChanged函数, // 在LifecycleBoundObserver 中记录状态,当生命周期变为活跃,就回去更新数据 if (!observer.shouldBeActive()) { observer.activeStateChanged(false); return; } // 此处判断观察者接收消息的次数是否大于等于 发送消息的次数(observer被创建之初verison=-1 ) if (observer.mLastVersion >= mVersion) { return; } observer.mLastVersion = mVersion; // 这里会执行传入的observer的onChanged方法 observer.mObserver.onChanged((T) mData); }
综上分析:LiveData的粘性事件:
通过同一个LiveData 在更改数据的时候调用 setValue(postValue 最终也会调用 setValue) 的时候内部维护的 mVersion 会自增1,mVersion 初始值是-1
在监听数据变化的时候,即调用 observer 监听的时候,每次内部都会在通过包装类中new ObserverWrapper,内部维护了一个mLastVersion变量,mLastVersion也是初始值为-1,所以注意了,每执行一次 observer 方法内部维护 mLastVersion 都会新创建而变为 -1 ,如果 mLastVersion 小于 mVersion 的时候就表示有新的变化没有回调 observer 的 onChanged 方法。
结论所以只要之前有发射过一次数据,那么后面注册的观察者都会接收到最精一次发射过的数据
这种情况被称为LiveData的粘性事件