@TryLoveCatch
2022-10-25T06:18:51.000000Z
字数 27699
阅读 1697
android Jetpack LiveData
https://www.jianshu.com/p/8c15cadb638f
LiveData是Google推出的一系列的框架组件的其中一个,它是一个可以被观察的数据持有类,能够感知Activity、Fragment等组件的生命周期。
LiveData 可以和生命周期绑定,当 Lifecycle(例如 Activity、Fragment 等)处于活跃状态时才进行数据回调,并在 Lifecycle 处于无效状态(DESTROYED)时自动移除数据监听行为,从而避免常见的内存泄露和 NPE 问题
一个观察者去观察LiveData后,当观察者的生命周期处于STARTED或RESUMED状态时(即onStart()、onResume()、onPause()),LiveData的数据发生变化,则会通知观察者;若观察者处于其他状态,即使LiveData的数据发生变化,也不会发出通知。
所以说,LiveData可以做到仅在组件处于活跃状态时才进行更新UI的操作
https://www.jianshu.com/p/8c15cadb638f
dependencies {//...def lifecycle_version = "1.1.1"//仅仅依赖LiveDataimplementation "android.arch.lifecycle:livedata:$lifecycle_version"}
google提倡LiveData配合ViewModel一起使用。
为了专注LiveData,这里先不用ViewModel,后面再补充说明如何跟ViewModel一起使用。直接看例子:
public class TestModel {private MutableLiveData<String> status;public MutableLiveData<String> getStatus() {if (status == null)status = new MutableLiveData<>();return status;}}
MutableLiveData继承自LiveData,表示可变数据。
这里创建一个保存String类型数据的LiveData。
public class TestActivity extends AppCompatActivity {private static final String TAG = "test";private TextView mTextView;private TestModel mTestModel;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test_activity);mTextView = findViewById(R.id.tv_test);init();}private void init() {//创建一个观察者去更新UIfinal Observer<String> statusObserver = new Observer<String>() {@Overridepublic void onChanged(@Nullable final String newName) {Log.d(TAG, "onChanged: " + newName);mTextView.setText(newName);}};//创建TestModel对象mTestModel = new TestModel();//观察LiveData对象//这里的this指的是LifecycleOwner,即LiveData会跟生命周期联系起来mTestModel.getStatus().observe(this, statusObserver);}}
observe(),可以对LiveData进行监听,需要传递一个LifecycleOwner参数进去,这表示LiveData会跟生命周期联系起来。
observeForever(),只需传递一个观察者进去就行,这意味着它跟生命周期没有任何关系,可以持续的观察,只要数据发生变化,都会通知观察者回调onChanged()。
public class TestActivity extends AppCompatActivity {private static final String TAG = "test";private TextView mTextView;private TestModel mTestModel;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.test_activity);mTextView = findViewById(R.id.tv_test);initVariable();}private void initVariable() {//创建一个观察者去更新UIfinal Observer<String> statusObserver = new Observer<String>() {@Overridepublic void onChanged(@Nullable final String newName) {Log.d(TAG, "onChanged: " + newName);mTextView.setText(newName);}};//创建TestModel对象mTestModel = new TestModel();//观察LiveData对象//这里的this指的是LifecycleOwner,即LiveData会跟生命周期联系起来mTestModel.getStatus().observe(this, statusObserver);mTestModel.getStatus().setValue("onCreate");}@Overrideprotected void onStart() {super.onStart();mTestModel.getStatus().setValue("onStart");}@Overrideprotected void onResume() {super.onResume();mTestModel.getStatus().setValue("onResume");}@Overrideprotected void onPause() {super.onPause();mTestModel.getStatus().setValue("onPause");}@Overrideprotected void onStop() {super.onStop();mTestModel.getStatus().setValue("onStop");}@Overrideprotected void onDestroy() {super.onDestroy();mTestModel.getStatus().setValue("onDestroy");}}
一个完整的生命周期走下来,其输出结果为:
07-26 22:03:34.798 20995-20995/com.test.start D/test: onChanged: onStart07-26 22:03:34.801 20995-20995/com.test.start D/test: onChanged: onResume07-26 22:03:36.456 20995-20995/com.test.start D/test: onChanged: onPause
可以看到,只在onStart()、onResume()、onPause()时观察者才会收到数据更新的通知,其他状态下即使更新了数据也不会收到通知。
比如说定位,我们希望有观察者的时候,开启定位,没有观察者的时候,就可以停止定位,没必要一直获取定位点
public class TestLiveData extends LiveData<Location> {private static TestLiveData sInstance;private LocationUtil mLocationUtil;//设计为单例模式public static TestLiveData getInstance() {if (sInstance == null) {sInstance = new TestLiveData();}return sInstance;}private TestLiveData() {//创建一个获取位置的对象mLocationUtil = new LocationUtil();}@Overrideprotected void onActive() {//开始获取位置信息mLocationUtil.start(mLocationListener);}@Overrideprotected void onInactive() {//停止获取位置信息mLocationUtil.stop();}//创建一个位置监听器private LocationListener mLocationListener = new LocationListener() {@Overridepublic void onReceiveLocation(Location location) {//接受到位置信息后,更新数据setValue(location);}};}
public class TestViewModel extends ViewModel {private MutableLiveData<Integer> mNumLiveData= new MutableLiveData<>();//通过Transformations.map()将Integer类型的值转换为String类型private LiveData<String> mStrLiveData = Transformations.map(mNumLiveData, new Function<Integer, String>() {@Overridepublic String apply(Integer name) {return name + "";}});//observe这个,获取Integer类型的数据public MutableLiveData<Integer> getNumLiveData() {return mNumLiveData;}//observe这个,获取string类型的数据public LiveData<String> getStrLiveData() {return mStrLiveData;}}
public class TestViewModel extends ViewModel {private MutableLiveData<String> mutableLiveData1 = new MutableLiveData<>();private MutableLiveData<String> mutableLiveData2 = new MutableLiveData<>();private MutableLiveData<Boolean> liveDataSwitch = new MutableLiveData<>();LiveData transformedLiveData= Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {@Overridepublic LiveData<String> apply(Boolean input) {if (input) {return mutableLiveData1;} else {return mutableLiveData2;}}});public MutableLiveData<String> getMutableLiveData1() {return mutableLiveData1;}public MutableLiveData<String> getMutableLiveData2() {return mutableLiveData2;}public MutableLiveData<Boolean> getLiveDataSwitch() {return liveDataSwitch;}public MutableLiveData<Boolean> getTransformedLiveData() {return transformedLiveData;}}// 使用getTransformedLiveData().observe(this, new Observer<String>() {@Overridepublic void onChanged(@Nullable final String s) {Log.d(TAG, "onChanged:" + s);}});getLiveDataSwitch().postValue(false);getMutableLiveData1().postValue("1111");getMutableLiveData2().postValue("2222");
当liveDataSwitch的值为true时返回mutableLiveData1,否则返回mutableLiveData2,可以用来切换监听的liveData
MediatorLiveData继承自MutableLiveData,它可以将多个LiveData数据源集合起来,可以达到一个组件监听多个LiveData数据变化的目的。
当任何一个MutableLiveData数据发生变化时,MediatorLiveData都可以感知到。
public class TestViewModel extends ViewModel {private MutableLiveData<String> mutableLiveData1 = new MutableLiveData<>();private MutableLiveData<String> mutableLiveData2 = new MutableLiveData<>();private MediatorLiveData liveDataMerger = new MediatorLiveData<String>();liveDataMerger.addSource(mutableLiveData1, new Observer() {@Overridepublic void onChanged(@Nullable String str) {liveDataMerger.setValue(str)}});liveDataMerger.addSource(mutableLiveData2, new Observer() {@Overridepublic void onChanged(@Nullable Object str) {liveDataMerger.setValue(str)}});public MutableLiveData<String> getLiveDataMerger() {return liveDataMerger;}public MutableLiveData<String> getMutableLiveData1() {return mutableLiveData1;}public MutableLiveData<Boolean> getMutableLiveData2() {return getMutableLiveData2;}}// 使用getLiveDataMerger().observe(this, new Observer<String>() {@Overridepublic void onChanged(@Nullable final String s) {Log.d(TAG, "onChanged:" + s);}});getMutableLiveData1().postValue("1111");getMutableLiveData2().postValue("2222");
MediatorLiveData相比于LiveData,主要是多了以下两个方法:
首先我们带着问题来看:
然后我们从使用方式入手,根据使用API来一步一步看一下内部是怎么实现的
LiveData 包含两个用于添加数据观察者(Observer)的方法,分别是
两个方法的区别对于外部来说只在于是否提供了生命周期安全的保障
observe(LifecycleOwner , Observer) 传入的 LifecycleOwner 参数意味着携带了 Lifecycle 对象,LiveData 内部就根据 Lifecycle 的生命周期事件的回调变化在合适的时机进行数据通知,并在 Lifecycle 对象处于 DESTROYED 状态时自动移除 Observer,这也是 LiveData 避免内存泄漏的最重要的一个点。
@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {//限定只能在主线程调用 observe 方法assertMainThread("observe");//当 Lifecycle 已经处于 DESTROYED 状态时,此时进行 observe 是没有意义的,直接返回if (owner.getLifecycle().getCurrentState() == DESTROYED) {// ignorereturn;}//根据传入参数构建一个新的代理 ObserverLifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);//将 observer 作为 key,wrapper 作为 value 进行存储//当 mObservers 不包含该 key 时,调用 putIfAbsent 会返回 null//当 mObservers 已包含该 key 时,调用 putIfAbsent 不会存储 key-value,并会返回之前保存的 valueObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);if (existing != null && !existing.isAttachedTo(owner)) {//走到此步,说明之前 LiveData 内部已经持有了 observer 对象,且该 observer 对象已经绑定了其它的 LifecycleOwner 对象//此时直接抛出异常throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {//observer 之前已经传进来过了,此处直接返回return;}owner.getLifecycle().addObserver(wrapper);}
上面的代码使用到了 LifecycleBoundObserver,它是抽象类 ObserverWrapper 的实现类。
ObserverWrapper 用于包装外部传进来的 Observer 对象,为子类定义好特定的抽象方法和共用逻辑,主要是提供了共用的状态分发函数。
private abstract class ObserverWrapper {//外部传进来的对 LiveData 进行数据监听的 Observerfinal Observer<? super T> mObserver;//用于标记 mObserver 是否处于活跃状态boolean mActive;//用于标记 Observer 内最后一个被回调的 value 的新旧程度int mLastVersion = START_VERSION;ObserverWrapper(Observer<? super T> observer) {mObserver = observer;}//用于获取当前 Lifecycle 是否处于活跃状态abstract boolean shouldBeActive();//用于判断 mObserver 是否和 LifecycleOwner(即 Lifecycle)有绑定关系boolean isAttachedTo(LifecycleOwner owner) {return false;}//移除 mObservervoid detachObserver() {}void activeStateChanged(boolean newActive) {if (newActive == mActive) {return;}// immediately set active state, so we'd never dispatch anything to inactive// ownermActive = newActive;//判断当前 LiveData 所有的 Observer 是否都处于非活跃状态boolean wasInactive = LiveData.this.mActiveCount == 0;//更新 LiveData 当前所有处于活跃状态的 Observer 的数量LiveData.this.mActiveCount += mActive ? 1 : -1;if (wasInactive && mActive) {//如果 LiveData 处于活跃状态的 Observer 数量从 0 变成了 1,//则回调 onActive 方法onActive();}if (LiveData.this.mActiveCount == 0 && !mActive) {//如果 LiveData 处于活跃状态的 Observer 数量从 1 变成了 0,//则回调 onInactive 方法onInactive();}if (mActive) {//如果 mObserver 变成了活跃状态,则向其回调新值dispatchingValue(this);}}}
主要是activeStateChanged(boolean newActive)方法:
boolean wasInactive = LiveData.this.mActiveCount == 0,这个LiveData.this.mActiveCount是当前LiveData里面处于活跃状态的Observer个数,所以wasInactive判断是当前整个LiveData是否有活跃状态的Observer,true表示所有Observer都处于非活跃状态,false表示至少有一个Observer处于活跃状态LiveData#onActive(),回调告知整个LiveData处于活跃LiveData#onInactive(),回调告知整个LiveData处于不活跃LiveData#dispatchingValue(this);,注意传入的参数值是this所以ObserverWrapper#activeStateChanged主要做了两件事:
LiveData#mActiveCount来判断整个LiveData的活跃状态,不活跃 -> 活跃回调LiveData#onActive(),活跃 -> 不活跃 回调LiveData#onInactive() 调用大概有三个地方:
ObserverWrapper 一共有两个子类:LifecycleBoundObserver 和 AlwaysActiveObserver,两者的差别就在于是否和生命周期相绑定。
LifecycleBoundObserver,它是抽象类 ObserverWrapper 的实现类,它也实现了 GenericLifecycleObserver或者LifecycleEventObserver 接口,从而可以收到 Lifecycle 的每次生命周期事件切换时的事件回调。
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {@NonNullfinal LifecycleOwner mOwner;LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {super(observer);mOwner = owner;}@Overrideboolean shouldBeActive() {//只有当 Lifecycle 的当前状态是 STARTED 或者 RESUMED 时//才认为 Lifecycle 是处于活跃状态return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}//LifecycleEventObserver 的实现方法//当 Lifecycle 的生命周期状态发生变化时就会调用此方法@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {//如果 Lifecycle 已经处于 DESTROYED 状态了,则主动移除 mObserver//这就是 LiveData 可以避免内存泄露最重要的一个点if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {removeObserver(mObserver);return;}activeStateChanged(shouldBeActive());}@Overrideboolean isAttachedTo(LifecycleOwner owner) {return mOwner == owner;}@Overridevoid detachObserver() {//移除 mObservermOwner.getLifecycle().removeObserver(this);}}
ObserverWrapper#activeStateChanged,这个上面已经说过了observeForever() 函数本身不会考虑外部所处的生命周期状态,只要数据发生变化时就会进行数据回调,因此 observeForever()函数是非生命周期安全的
@MainThreadpublic void observeForever(@NonNull Observer<? super T> observer) {//限定只能在主线程调用 observe 方法assertMainThread("observeForever");AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);if (existing instanceof LiveData.LifecycleBoundObserver) {//会走到这一步,是因为之前已经先用该 observer 对象调用了 observe(LifecycleOwner,Observer)//这里直接抛出异常throw new IllegalArgumentException("Cannot add the same observer"+ " with different lifecycles");}if (existing != null) {//如果之前已经添加过 observer 对象了的话,则直接返回return;}//主动触发 activeStateChanged 函数,因为当前 LiveData 可能已经被设置值了wrapper.activeStateChanged(true);}
observe(LifecycleOwner,Observer)方法,则直接抛出异常。因为如果允许 observer 同时调用observeForever() 和 observe() 函数,则当数据发生变化时,这可能会造成 Lifecycle 处于 DESTROYED 状态时还进行了数据回调,而这破坏了 observe(LifecycleOwner,Observer) 所期望的生命周期安全ObserverWrapper#activeStateChanged(true),不需要关系生命周期回调,直接传入trueAlwaysActiveObserver,它也是抽象类 ObserverWrapper 的实现类,其 shouldBeActive()返回值固定为 true,意味着只要有数据变化都会进行回调。
所以使用 observeForever() 函数一定要在过后主动移除 Observer,避免内存泄露和 NPE
private class AlwaysActiveObserver extends ObserverWrapper {AlwaysActiveObserver(Observer<? super T> observer) {super(observer);}@Overrideboolean shouldBeActive() {//使其固定返回 true,则意味着只要有数据变化就都进行数据回调return true;}}
removeObserver 的方式一共有两种,逻辑都比较简单
//移除指定的 Observer 对象@MainThreadpublic void removeObserver(@NonNull final Observer<? super T> observer) {assertMainThread("removeObserver");ObserverWrapper removed = mObservers.remove(observer);if (removed == null) {return;}removed.detachObserver();removed.activeStateChanged(false);}//通过循环遍历移除所有和特定 LifecycleOwner 绑定的 Observer 对象@SuppressWarnings("WeakerAccess")@MainThreadpublic void removeObservers(@NonNull final LifecycleOwner owner) {assertMainThread("removeObservers");for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {if (entry.getValue().isAttachedTo(owner)) {removeObserver(entry.getKey());}}}
更新 LiveData 的值的方法一共有两个,分别是:
private volatile Object mData;private int mVersion;@MainThreadprotected void setValue(T value) {assertMainThread("setValue");//更新当前 value 的版本号,即 value 的新旧程度mVersion++;mData = value;dispatchingValue(null);}
dispatchingValue(null),跟之前说的ObserverWrapper#activeStateChanged()不同,这里调用的时候,传入参数为null。dispatchingValue() 这个被提到了很多次了
//用于标记当前是否正处于向 mObservers 发布 value 的过程private boolean mDispatchingValue;//用于标记当前正在发布的 value 是否已经失效//在 value 还未向所有 Observer 发布完成的时候,新 value 已经到来,此时旧 value 就是处于失效状态@SuppressWarnings("FieldCanBeLocal")private boolean mDispatchInvalidated;//initiator 为 null 则说明需要遍历回调整个 mObservers//initiator 不为 null 则说明仅回调 initiator 本身@SuppressWarnings("WeakerAccess") /* synthetic access */void dispatchingValue(@Nullable ObserverWrapper initiator) {if (mDispatchingValue) {//如果 mDispatchingValue 为 true,说明当前正处于向 mObservers 发布 mData 的过程中//而 dispatchingValue 方法只会在主线程进行调用,所以会出现 mDispatchingValue 为 true 的情况//说明 Observer 的 onChanged 方法内部又主动向 LiveData setValue//则将 mDispatchInvalidated 置为 true,用于标明有新值到来,正在回调的值是已经过时的了mDispatchInvalidated = true;return;}//用于标记当前正处于向 mObservers 发布 mData 的过程中mDispatchingValue = true;do {mDispatchInvalidated = false;if (initiator != null) {considerNotify(initiator);initiator = null;} else {for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {considerNotify(iterator.next().getValue());if (mDispatchInvalidated) {//如果 mDispatchInvalidated 为 true,则中断继续遍历过程//用新值来重新循环一遍break;}}}} while (mDispatchInvalidated);mDispatchingValue = false;}
dispatchingValue(ObserverWrapper) 关于这个入参有两种情况: do..while呢? 这里,我有一个疑惑:
从逻辑上看 dispatchingValue() 函数只会在主线程进行调用,那么 dispatchingValue() 一定是会在执行完毕后才被再次执行,不存在多线程同时调用的情况,那么此时 mDispatchingValue 和 mDispatchInvalidated 两个变量就没有存在的必要了吧
private void considerNotify(ObserverWrapper observer) {//如果 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.//此处判断主要是为了照顾 LifecycleBoundObserver//由于 Lifecycle 有可能状态值 State 已经切换到了非活跃状态,但 LifecycleBoundObserver 还未收到事件通知//所以为了避免意外情况,此处主动检查 observer 的活跃状态并判断是否需要更新其活跃状态if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}//根据 observer 本部的 value 版本号 mLastVersion 来决定是否需要向其进行回调//为了避免重复向某个 observer 回调值,所以此处需要判断下if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;observer.mObserver.onChanged((T) mData);}
ObserverWrapper处于非活跃状态,直接returnLifecycleBoundObserver 还未收到事件通知,所以主动调用一下Lifecycle 的方法,来判断是否处于活跃状态ObserverWrapper#mLastVersion和LiveData#mVersion,来判断是否需要分发数据ObserverWrapper#Observer#onChanged()postValue(T) 函数不限定调用者所在线程,不管是主线程还是子线程都可以调用,因此是存在多线程竞争的可能性的,postValue(T) 函数的重点旧在于需要理解其从子线程切换到主线程之间的状态变化
@SuppressWarnings("WeakerAccess") /* synthetic access */final Object mDataLock = new Object();@SuppressWarnings("WeakerAccess") /* synthetic access *///mPendingData 的默认值//当 mPendingData 等于 NOT_SET 时说明当前 LiveData 没有值需要通过 postValue 回调static final Object NOT_SET = new Object();volatile Object mPendingData = NOT_SET;//用于在主线程对值进行回调private final Runnable mPostValueRunnable = new Runnable() {@SuppressWarnings("unchecked")@Overridepublic void run() {Object newValue;synchronized (mDataLock) {//通过加锁可以确保 newValue 指向的是当前最新值newValue = mPendingData;//重置 mPendingDatamPendingData = NOT_SET;}setValue((T) newValue);}};protected void postValue(T value) {boolean postTask;//加锁以保证 mPendingData 值能够一直指向最新值synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}//如果 postTask 为 false,则说明当前有旧值需要通过 postValue 进行回调//因为 postValue 可以在子线程调用,而 Observer 的 onChanged(value) 方法肯定是要在主线程被调用//从子线程切到主线程之间是有段时间间隔的//等到 mPostValueRunnable 真正执行时让其直接发送最新值 mPendingData 即可,所以此处直接返回if (!postTask) {return;}//向主线程发送一个 runnable,主要是为了在子线程调用 postValue,在主线程进行值回调ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}
调用线程:
主线程:
所以当多个线程同时调用,在postTask为false,直接return的时候,其实是会导致丢值的。在单个线程连续调用的时候,也会导致这个问题,为什么?因为调用Handler#post(),会延迟调用,所以也会导致这个问题。
LiveData 的 setValue() 和 postValue() 方法的访问权限都是 protected,因此我们在日常开发中基本都是使用其子类
MutableLiveData 的源码很简单,只是将 setValue() 和 postValue() 方法的访问权限提升为了 public,从而让外部可以直接调用这两个方法:
public class MutableLiveData<T> extends LiveData<T> {/*** Creates a MutableLiveData initialized with the given {@code value}.** @param value initial value*/public MutableLiveData(T value) {super(value);}/*** Creates a MutableLiveData with no value assigned to it.*/public MutableLiveData() {super();}@Overridepublic void postValue(T value) {super.postValue(value);}@Overridepublic void setValue(T value) {super.setValue(value);}}
MediatorLiveData 是 MutableLiveData 的子类,可以添加多个LiveData数据源,监听这个多个LiveData,在他们的Observer回调的时候,调用MediatorLiveData自己的setValue来通知自己的Observer,具体例子可以看上面关于MediatorLiveData的使用例子
private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();@MainThreadpublic <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) {//走到这一步,说明之前已经传进来过同个 source 对象//但当时传的 Observer 对象与本地传递的 Observer 对象不是同一个//直接抛出异常throw new IllegalArgumentException("This source was already added with the different observer");}if (existing != null) {//走到此步,说明之间已经用相同的 source 和 onChanged 对象调用过 addSource 方法//所以直接返回return;}//如果 MediatorLiveData 当前有处于活跃状态的 Observer 对其进行监听//则调用 Source 对象的 plug() 函数if (hasActiveObservers()) {e.plug();}}
MediatorLiveData的源码其实很类似于LiveData,最重要的是增加了addSource()和removeSource():
Source#plug()
//移除对数据源的监听行为@MainThreadpublic <S> void removeSource(@NonNull LiveData<S> toRemote) {Source<?> source = mSources.remove(toRemote);if (source != null) {source.unplug();}}
代码很简单:
private static class Source<V> implements Observer<V> {final LiveData<V> mLiveData;final Observer<? super V> mObserver;int mVersion = START_VERSION;Source(LiveData<V> liveData, final Observer<? super V> observer) {mLiveData = liveData;mObserver = observer;}//对外部数据源 mLiveData 进行监听void plug() {mLiveData.observeForever(this);}//移除对外部数据源 mLiveData 的监听void unplug() {mLiveData.removeObserver(this);}@Overridepublic void onChanged(@Nullable V v) {if (mVersion != mLiveData.getVersion()) {mVersion = mLiveData.getVersion();mObserver.onChanged(v);}}}
observeForever(),所以有两个后果 removeObserver(),避免出现其他问题所以虽然提供了unplug(),但是如果使用者没有调用呢,怎么能保证unplug()一定被调用呢?
MediatorLiveData复写了LiveData的onActive()和onInactive():
@CallSuper@Overrideprotected void onActive() {for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {source.getValue().plug();}}@CallSuper@Overrideprotected void onInactive() {for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {source.getValue().unplug();}}
再说一下用法,根据用法我们来理解一下:
- MediatorLiveData#addSource(LiveData, Observer)
- MediatorLiveData#addSource(LiveData, Observer)
- MediatorLiveData#addSource(LiveData, Observer)
- MediatorLiveData#Observer(Observer)
为了描述简单,我们说MediatorLiveData为父LiveData,addSource添加的LiveData为子LiveData:
addSource()来添加多个子LiveData,并进行监听observeForever()来进行监听的,所以不具有生命周期安全observe(LifecycleOwner, Observer<T>)来进行监听自己本身的数据变化Transformations 类是 lifecycle-livedata 库提供的一个工具类型的方法类,提供了三个静态方法用于简化对 MediatorLiveData 的使用,这里再来依次介绍下:
map(LiveData , Function) 函数用于简化向 MediatorLiveData 添加数据源的过程。大多数情况下,我们在使用 MediatorLiveData 时就是先将数据源类型 X 转换我们的目标数据类型 Y,然后再通过 setValue(Y) 进行数据回调。map 函数将这个数据类型转换过程抽象为了接口 Function,将 setValue(Y) 过程隐藏在了 map 函数内部
@MainThread@NonNullpublic 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>() {@Overridepublic void onChanged(@Nullable X x) {result.setValue(mapFunction.apply(x));}});return result;}public interface Function<I, O> {/*** Applies this function to the given input.** @param input the input* @return the function result.*/O apply(I input);}
switchMap,可以用来切换不同的子LiveData
@MainThread@NonNullpublic static <X, Y> LiveData<Y> switchMap(@NonNull LiveData<X> source,@NonNull final Function<X, LiveData<Y>> switchMapFunction) {final MediatorLiveData<Y> result = new MediatorLiveData<>();//先内部构建一个 MediatorLiveData,然后将 source 作为其数据源result.addSource(source, new Observer<X>() {//缓存每次的请求结果LiveData<Y> mSource;@Overridepublic void onChanged(@Nullable X x) {//触发外界根据请求值 x 获得 LiveData 结果值的逻辑//对应上面例子的 getUsersWithNameLiveData 方法//这个过程是惰性的,即只有数据源 source 发生了变化才会触发请求LiveData<Y> newLiveData = switchMapFunction.apply(x);if (mSource == newLiveData) {//如果 newLiveData 之前已经拿到了,则不必重复监听其回调结果//直接返回即可return;}if (mSource != null) {//新值到来,移除对旧值的监听result.removeSource(mSource);}mSource = newLiveData;if (mSource != null) {result.addSource(mSource, new Observer<Y>() {@Overridepublic void onChanged(@Nullable Y y) {//等到拿到了getUsersWithNameLiveData 的请求结果后//就将结果值回调出去result.setValue(y);}});}}});return result;}
distinctUntilChanged() 函数用于过滤掉连续重复的回调值,只有本次的回调结果和上次不一致,本次的回调值才被认为是有效的
@MainThread@NonNullpublic static <X> LiveData<X> distinctUntilChanged(@NonNull LiveData<X> source) {final MediatorLiveData<X> outputLiveData = new MediatorLiveData<>();outputLiveData.addSource(source, new Observer<X>() {//用于是否是第一次收到回调值boolean mFirstTime = true;@Overridepublic void onChanged(X currentValue) {final X previousValue = outputLiveData.getValue();//等式成立的条件一共有三种,满足其一即可//1. 是第一次收到回调值,即 mFirstTime 为 true//2. 上次的回调值为 null,本次的回调值不为 null//3. 上次的回调值不为 null,且与本次的回调值不相等if (mFirstTime|| (previousValue == null && currentValue != null)|| (previousValue != null && !previousValue.equals(currentValue))) {mFirstTime = false;outputLiveData.setValue(currentValue);}}});return outputLiveData;}
感觉LiveData的源码相比Lifecycle,比较清晰简单
https://juejin.cn/post/6903096576734920717
https://tech.meituan.com/2018/07/26/android-livedatabus.html
livedata的粘性问题
使用SingleLiveEvent,虽然解决了粘性的问题,但是只支持单个观察者
还有一个问题,如果当前view不可见,那么只会调用setValue的,但是不会通知观察者,也就是不会调用onChanged,所以AtomicBoolean的值没有为置为false,在下次注册的时候,还是会通知一次
所以SingleLiveEvent只是解决了,多次注册时,非首次注册的观察者会获取到数据的问题,并没有解决首次注册的粘性问题
参考:https://github.com/JeremyLiao/LiveEventBus
https://yutiantina.github.io/2019/09/20/%E5%9F%BA%E4%BA%8ELiveData%E5%AE%9E%E7%8E%B0%E4%BA%8B%E4%BB%B6%E6%80%BB%E7%BA%BF%E6%80%9D%E8%B7%AF%E5%92%8C%E6%96%B9%E6%A1%88/
https://zhuanlan.zhihu.com/p/419512610
我们来回顾一下,之前说过LiveData有三个特性:
- 只在 Observer 至少处于 STARTED 状态时才能收到事件通知。Activity 只有在 onStart 方法后且 onPause 方法前才能收到事件通知
- LiveData 是黏性的。假设存在一个静态的 LiveData 变量,且已经包含了数据,对其进行监听的 Activity 都会收到其当前值的回调通知,即收到了黏性消息。这个概念就类似于 EventBus 中的 StickyEvent
- 中间值可以被新值直接掩盖。当 Activity 处于后台时,如果 LiveData 先后接收到了多个值,那么当 Activity 回到前台时也只会收到最新值的一次回调,中间值直接被掩盖了,Activity 完全不会感受到中间值的存在
以上三点特性都是由于界面层的特点来决定的:
https://www.jianshu.com/p/8c15cadb638f
http://liuwangshu.cn/application/jetpack/5-livedata-theory.html
https://github.com/leavesC/AndroidGuide/blob/gitbook/jetpack/LiveData%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90.md
https://github.com/leavesC/AndroidGuide/blob/gitbook/jetpack/LiveData%E8%A1%8D%E7%94%9F.md