写点什么

MVVM 系列之二:LiveData,android 程序开发教程

用户头像
Android架构
关注
发布于: 2021 年 11 月 05 日

此例子把 Integer 类型的 liveData1 修改为 String 类型的 liveDataMap。结果如下:


2020-12-06 17:01:56.095 21998-21998/com.hfy.androidlearning I/Lifecycle_Test: apply: 100 + Transformations.map


2020-12-06 17:01:56.095 21998-21998/com.hfy.androidlearning I/Lifecycle_Test: onChanged1: 100 + Transformations.map

2.3.2 数据切换 - Transformations.switchMap

如果想要根据某个值 切换观察不同 LiveData 数据,则可以使用 Transformations.switchMap()方法。


//两个 liveData,由 liveDataSwitch 决定 返回哪个 livaData 数据


MutableLiveData<String> liveData3 = new MutableLiveData<>();


MutableLiveData<String> liveData4 = new MutableLiveData<>();


//切换条件 LiveData,liveDataSwitch 的 value 是切换条件


MutableLiveData<Boolean> liveDataSwitch = new MutableLiveData<>();


//liveDataSwitchMap 由 switchMap()方法生成,用于添加观察者


LiveData<String> liveDataSwitchMap = Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {


@Override


public LiveData<String> apply(Boolean input) {


//这里是具体切换逻辑:根据 liveDataSwitch 的 value 返回哪个 liveData


if (input) {


return liveData3;


}


return liveData4;


}


});


liveDataSwitchMap.observe(this, new Observer<String>() {


@Override


public void onChanged(String s) {


Log.i(TAG, "onChanged2: " + s);


}


});


boolean switchValue = true;


liveDataSwitch.setValue(switchValue);//设置切换条件值


liveData3.setValue("liveData3");


liveData4.setValue("liveData4");


liveData3、liveData4 是两个数据源,有一个判断条件来决定 取哪一个数据 ,这个条件就是 liveDataSwitch,如果值为 true 则取 liveData3,false 则取 liveData4。 Transformations.switchMap()就用于实现这一逻辑,返回值 liveDataSwitchMap 添加观察者就可以了。 结果如下:


2020-12-06 17:33:53.844 27347-27347/com.hfy.androidlearning I/Lifecycle_Test: switchValue=true


2020-12-06 17:33:53.847 27347-27347/com.hfy.androidlearning I/Lifecycle_Test: onChanged2: liveData3


2020-12-06 17:34:37.600 27628-27628/com.hfy.androidlearning I/Lifecycle_Test: switchValue=false


2020-12-06 17:34:37.602 27628-27628/com.hfy.androidlearning I/Lifecycle_Test: onChanged2: liveData4


(Transformations 对 LivaData 这两个用法和 Rxjava 简直一毛一样)

2.3.3 观察多个数据 - MediatorLiveData

MediatorLiveData 是 LiveData 的子类,允许合并多个 LiveData 源。只要任何原始的 LiveData 源对象发生更改,就会触发 MediatorLiveData 对象的观察者。


MediatorLiveData<String> mediatorLiveData = new MediatorLiveData<>();


MutableLiveData<String> liveData5 = new MutableLiveData<>();


MutableLiveData<String> liveData6 = new MutableLiveData<>();


//添加 源 LiveData


mediatorLiveData.addSource(liveData5, new Observer<String>() {


@Override


public void onChanged(String s) {


Log.i(TAG, "onChanged3: " + s);


mediatorLiveData.setValue(s);


}


});


//添加 源 LiveData


mediatorLiveData.addSource(liveData6, new Observer<String>() {


@Override


public void onChanged(String s) {


Log.i(TAG, "onChanged4: " + s);


mediatorLiveData.setValue(s);


}


});


//添加观察


mediatorLiveData.observe(this, new Observer<String>() {


@Override


public void onChanged(String s) {


Log.i(TAG, "onChanged5: "+s);


//无论 liveData5、liveData6 更新,都可以接收到


}


});


liveData5.setValue("liveData5");


//liveData6.setValue("liveData6");


例如,如果界面中有可以从本地数据库或网络更新的 LiveData 对象,则可以向 MediatorLiveData 对象添加以下源:


  • 与存储在本地数据库中的数据关联的 liveData5

  • 与从网络访问的数据关联的 liveData6


Activity 只需观察 MediatorLiveData 对象即可从这两个源接收更新。 结果如下:


2020-12-06 17:56:17.870 29226-29226/com.hfy.androidlearning I/Lifecycle_Test: onChanged3: liveData5


2020-12-06 17:56:17.870 29226-29226/com.hfy.androidlearning I/Lifecycle_Test: onChanged5: liveData5


(Transformations 也是对 MediatorLiveData 的使用。)


LiveData 的使用就讲完了,下面开始源码分析。


3、源码分析


======


前面提到 LiveData 几个特点,能感知生命周期状态变化、不用手动解除观察等等,这些是如何做到的呢?


3.1 添加观察者




LiveData 原理是观察者模式,下面就先从 LiveData.observe()方法看起:


/**


  • 添加观察者. 事件在主线程分发. 如果 LiveData 已经有数据,将直接分发给 observer。

  • 观察者只在 LifecycleOwner 活跃时接受事件,如果变为 DESTROYED 状态,observer 自动移除。

  • 当数据在非活跃时更新,observer 不会接收到。变为活跃时 将自动接收前面最新的数据。

  • LifecycleOwner 非 DESTROYED 状态时,LiveData 持有 observer 和 owner 的强引用,DESTROYED 状态时自动移除引用。

  • @param owner 控制 observer 的 LifecycleOwner

  • @param observer 接收事件的 observer


*/


@MainThread


public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {


assertMainThread("observe");


if (owner.getLifecycle().getCurrentState() == DESTROYED) {


// LifecycleOwner 是 DESTROYED 状态,直接忽略


return;


}


//使用 LifecycleOwner、observer 组装成 LifecycleBoundObserver,添加到 mObservers 中


Li


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


fecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);


ObserverWrapper existing = mObservers 中.putIfAbsent(observer, wrapper);


if (existing != null && !existing.isAttachedTo(owner)) {


//!existing.isAttachedTo(owner)说明已经添加到 mObservers 中的 observer 指定的 owner 不是传进来的 owner,就会报错“不能添加同一个 observer 却不同 LifecycleOwner”


throw new IllegalArgumentException("Cannot add the same observer"


  • " with different lifecycles");


}


if (existing != null) {


return;//这里说明已经添加到 mObservers 中,且 owner 就是传进来的 owner


}


owner.getLifecycle().addObserver(wrapper);


}


首先是判断 LifecycleOwner 是 DESTROYED 状态,就直接忽略,不能添加。接着使用 LifecycleOwner、observer 组装成 LifecycleBoundObserver 包装实例 wrapper,使用 putIfAbsent 方法 observer-wrapper 作为 key-value 添加到观察者列表 mObservers 中。(putIfAbsent 意思是只有列表中没有这个 observer 时才会添加。)


然后对添加的结果进行判断,如果 mObservers 中已经存在此 observer key,但 value 中的 owner 不是传进来的 owner,就会报错“不能添加同一个 observer 却是不同 LifecycleOwner”。如果是相同的 owner,就直接 returne。


最后用 LifecycleOwner 的 Lifecycle 添加 observer 的封装 wrapper。


另外,再看 observeForever 方法:


@MainThread


public void observeForever(@NonNull Observer<? super T> observer) {


assertMainThread("observeForever");


AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);


ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);


if (existing instanceof LiveData.LifecycleBoundObserver) {


throw new IllegalArgumentException("Cannot add the same observer"


  • " with different lifecycles");


}


if (existing != null) {


return;


}


wrapper.activeStateChanged(true);


}


和 observe()类似,只不过 会认为观察者一直是活跃状态,且不会自动移除观察者。


3.2 事件回调




LiveData 添加了观察者 LifecycleBoundObserver,接着看如何进行回调的:


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() { //至少是 STARTED 状态


return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);


}


@Override


public void onStateChanged(@NonNull LifecycleOwner source,


@NonNull Lifecycle.Event event) {


if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {


removeObserver(mObserver);//LifecycleOwner 变成 DESTROYED 状态,则移除观察者


return;


}


activeStateChanged(shouldBeActive());


}


@Override


boolean isAttachedTo(LifecycleOwner owner) {


return mOwner == owner;


}


@Override


void detachObserver() {


mOwner.getLifecycle().removeObserver(this);


}


}


LifecycleBoundObserver 是 LiveData 的内部类,是对原始 Observer 的包装,把 LifecycleOwner 和 Observer 绑定在一起。当 LifecycleOwner 处于活跃状态,就称 LifecycleBoundObserver 是活跃的观察者。


它实现自接口 LifecycleEventObserver,实现了 onStateChanged 方法。上一篇[Lifecycle](


)中提到 onStateChanged 是生命周期状态变化的回调。


在 LifecycleOwner 生命周期状态变化时 判断如果是 DESTROYED 状态,则移除观察者。LiveData 自动移除观察者特点就来源于此。 如果不是 DESTROYED 状态,将调用父类 ObserverWrapper 的 activeStateChanged()方法处理 这个生命周期状态变化,shouldBeActive()的值作为参数,至少是 STARTED 状态为 true,即活跃状态为 true。


private abstract class ObserverWrapper {


...


void activeStateChanged(boolean newActive) {


if (newActive == mActive) {


return;//活跃状态 未发生变化时,不会处理。


}


mActive = newActive;


boolean wasInactive = LiveData.this.mActiveCount == 0;//没有活跃的观察者


LiveData.this.mActiveCount += mActive ? 1 : -1;//mActive 为 true 表示变为活跃


if (wasInactive && mActive) {


onActive();//活跃的观察者数量 由 0 变为 1


}


if (LiveData.this.mActiveCount == 0 && !mActive) {


onInactive(); //活跃的观察者数量 由 1 变为 0


}


if (mActive) {


dispatchingValue(this);//观察者变为活跃,就进行数据分发


}


}


}


ObserverWrapper 也是 LiveData 的内部类。mActive 是 ObserverWrapper 的属性,表示此观察者是否活跃。如果活跃状态 未发生变化时,不会处理。


LiveData.this.mActiveCount == 0 是指 LiveData 的活跃观察者数量。活跃的观察者数量 由 0 变为 1、由 1 变为 0 会分别调用 LiveData 的 onActive()、onInactive()方法。这就是前面提到的扩展使用的回调方法。


最后观察者变为活跃,就使用 LiveData 的 dispatchingValue(observerWrapper)进行数据分发:


void dispatchingValue(@Nullable ObserverWrapper initiator) {


if (mDispatchingValue) {


mDispatchInvalidated = true;//如果当前正在分发,则分发无效,return


return;


}


mDispatchingValue = true; //标记正在分发


do {


mDispatchInvalidated = false;


if (initiator != null) {


considerNotify(initiator); //observerWrapper 不为空,使用 considerNotify()通知真正的观察者


initiator = null;


} else { //observerWrapper 为空,遍历通知所有的观察者


for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =


mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {


considerNotify(iterator.next().getValue());


if (mDispatchInvalidated) {


break;


}


}


}


} while (mDispatchInvalidated);


mDispatchingValue = false;


}


如果当前正在分发,则分发无效;observerWrapper 不为空,就使用 considerNotify()通知真正的观察者,observerWrapper 为空 则遍历通知所有的观察者。 observerWrapper 啥时候为空呢?这里先留个疑问。 继续看 considerNotify()方法:


private void considerNotify(ObserverWrapper observer) {


if (!observer.mActive) {


return; //观察者非活跃 return


}


//若当前 observer 对应 owner 非活跃,就会再调用 activeStateChanged 方法,并传入 false,其内部会再次判断


if (!observer.shouldBeActive()) {


observer.activeStateChanged(false);


return;


}


if (observer.mLastVersion >= mVersion) {


return;


}


observer.mLastVersion = mVersion;


observer.mObserver.onChanged((T) mData);//回调真正的 mObserver 的 onChanged 方法


}


先进行状态检查:观察者是非活跃就 return;若当前 observer 对应的 owner 非活跃,就会再调用 activeStateChanged 方法,并传入 false,其内部会再次判断。最后回调真正的 mObserver 的 onChanged 方法,值是 LivaData 的变量 mData。


到这里回调逻辑也通了。


3.3 数据更新




LivaData 数据更新可以使用 setValue(value)、postValue(value),区别在于 postValue(value)用于 子线程:


//LivaData.java


private final Runnable mPostValueRunnable = new Runnable() {


@SuppressWarnings("unchecked")


@Override


public void run() {


Object newValue;


synchronized (mDataLock) {


newValue = mPendingData;


mPendingData = NOT_SET;


}


setValue((T) newValue); //也是走到 setValue 方法


}


};


protected void postValue(T value) {


boolean postTask;


synchronized (mDataLock) {


postTask = mPendingData == NOT_SET;


mPendingData = value;


}


if (!postTask) {


return;


}


ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);//抛到主线程


}


postValue 方法把 Runable 对象 mPostValueRunnable 抛到主线程,其 run 方法中还是使用的 setValue(),继续看:


@MainThread


protected void setValue(T value) {


assertMainThread("setValue");


mVersion++;


mData = value;


dispatchingValue(null);


}


setValue()把 value 赋值给 mData,然后调用 dispatchingValue(null),参数是 null,对应前面提到的 observerWrapper 为空的场景,即 遍历所有观察者 进行分发回调。


到这里观察者模式完整的实现逻辑就梳理清晰了:LivaData 通过 observe()添加 与 LifecycleOwner 绑定的观察者;观察者变为活跃时回调最新的数据;使用 setValue()、postValue()更新数据时会通知回调所有的观察者。


3.4 Transformations 原理




最后来看下 Transformations 的 map 原理,如何实现数据修改的。switchMap 类似的。


//Transformations.java


public static <X, Y> LiveData<Y> map(@NonNull LiveData<X> source,@NonNull final Function<X, Y> mapFunction) {


final MediatorLiveData<Y> result = new MediatorLiveData<>();


result.addSource(source, new Observer<X>() {


@Override


public void onChanged(@Nullable X x) {


result.setValue(mapFunction.apply(x));


}


});


return result;


}


new 了一个 MediatorLiveData 实例,然后将 传入的 livaData、new 的 Observer 实例作为参数 调用 addSource 方法:


//MediatorLiveData.java


public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {


Source<S> e = new Source<>(source, onChanged);


Source<?> existing = mSources.putIfAbsent(source, e);


if (existing != null && existing.mObserver != onChanged) {


throw new IllegalArgumentException(


"This source was already added with the different observer");


}


if (existing != null) {


return;


}


if (hasActiveObservers()) {


//MediatorLiveData 有活跃观察者,就 plug


e.plug();


}


}


MediatorLiveData 是 LiveData 的子类,用来观察其他的 LiveData 并在其 OnChanged 回调时 做出响应。传入的 livaData、Observer 包装成 Source 实例,添加到列表 mSources 中。


如果 MediatorLiveData 有活跃观察者,就调用 plug():


//MediatorLiveData.java


private static class Source<V> implements Observer<V> {


final LiveData<V> mLiveData;


final Observer<? super V> mObserver;


int mVersion = START_VERSION;

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
MVVM系列之二:LiveData,android程序开发教程