[关闭]
@TryLoveCatch 2022-10-25T14:18:51.000000Z 字数 27699 阅读 1422

Jetpack之LiveData

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

添加依赖

  1. dependencies {
  2. //...
  3. def lifecycle_version = "1.1.1"
  4. //仅仅依赖LiveData
  5. implementation "android.arch.lifecycle:livedata:$lifecycle_version"
  6. }

创建LiveData对象

google提倡LiveData配合ViewModel一起使用。
为了专注LiveData,这里先不用ViewModel,后面再补充说明如何跟ViewModel一起使用。直接看例子:

  1. public class TestModel {
  2. private MutableLiveData<String> status;
  3. public MutableLiveData<String> getStatus() {
  4. if (status == null)
  5. status = new MutableLiveData<>();
  6. return status;
  7. }
  8. }

MutableLiveData继承自LiveData,表示可变数据。
这里创建一个保存String类型数据的LiveData。

监听

  1. public class TestActivity extends AppCompatActivity {
  2. private static final String TAG = "test";
  3. private TextView mTextView;
  4. private TestModel mTestModel;
  5. @Override
  6. protected void onCreate(@Nullable Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.test_activity);
  9. mTextView = findViewById(R.id.tv_test);
  10. init();
  11. }
  12. private void init() {
  13. //创建一个观察者去更新UI
  14. final Observer<String> statusObserver = new Observer<String>() {
  15. @Override
  16. public void onChanged(@Nullable final String newName) {
  17. Log.d(TAG, "onChanged: " + newName);
  18. mTextView.setText(newName);
  19. }
  20. };
  21. //创建TestModel对象
  22. mTestModel = new TestModel();
  23. //观察LiveData对象
  24. //这里的this指的是LifecycleOwner,即LiveData会跟生命周期联系起来
  25. mTestModel.getStatus().observe(this, statusObserver);
  26. }
  27. }

更新数据

  1. public class TestActivity extends AppCompatActivity {
  2. private static final String TAG = "test";
  3. private TextView mTextView;
  4. private TestModel mTestModel;
  5. @Override
  6. protected void onCreate(@Nullable Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.test_activity);
  9. mTextView = findViewById(R.id.tv_test);
  10. initVariable();
  11. }
  12. private void initVariable() {
  13. //创建一个观察者去更新UI
  14. final Observer<String> statusObserver = new Observer<String>() {
  15. @Override
  16. public void onChanged(@Nullable final String newName) {
  17. Log.d(TAG, "onChanged: " + newName);
  18. mTextView.setText(newName);
  19. }
  20. };
  21. //创建TestModel对象
  22. mTestModel = new TestModel();
  23. //观察LiveData对象
  24. //这里的this指的是LifecycleOwner,即LiveData会跟生命周期联系起来
  25. mTestModel.getStatus().observe(this, statusObserver);
  26. mTestModel.getStatus().setValue("onCreate");
  27. }
  28. @Override
  29. protected void onStart() {
  30. super.onStart();
  31. mTestModel.getStatus().setValue("onStart");
  32. }
  33. @Override
  34. protected void onResume() {
  35. super.onResume();
  36. mTestModel.getStatus().setValue("onResume");
  37. }
  38. @Override
  39. protected void onPause() {
  40. super.onPause();
  41. mTestModel.getStatus().setValue("onPause");
  42. }
  43. @Override
  44. protected void onStop() {
  45. super.onStop();
  46. mTestModel.getStatus().setValue("onStop");
  47. }
  48. @Override
  49. protected void onDestroy() {
  50. super.onDestroy();
  51. mTestModel.getStatus().setValue("onDestroy");
  52. }
  53. }

一个完整的生命周期走下来,其输出结果为:

  1. 07-26 22:03:34.798 20995-20995/com.test.start D/test: onChanged: onStart
  2. 07-26 22:03:34.801 20995-20995/com.test.start D/test: onChanged: onResume
  3. 07-26 22:03:36.456 20995-20995/com.test.start D/test: onChanged: onPause

可以看到,只在onStart()、onResume()、onPause()时观察者才会收到数据更新的通知,其他状态下即使更新了数据也不会收到通知。

小结

扩展

自定义LiveData

比如说定位,我们希望有观察者的时候,开启定位,没有观察者的时候,就可以停止定位,没必要一直获取定位点

  1. public class TestLiveData extends LiveData<Location> {
  2. private static TestLiveData sInstance;
  3. private LocationUtil mLocationUtil;
  4. //设计为单例模式
  5. public static TestLiveData getInstance() {
  6. if (sInstance == null) {
  7. sInstance = new TestLiveData();
  8. }
  9. return sInstance;
  10. }
  11. private TestLiveData() {
  12. //创建一个获取位置的对象
  13. mLocationUtil = new LocationUtil();
  14. }
  15. @Override
  16. protected void onActive() {
  17. //开始获取位置信息
  18. mLocationUtil.start(mLocationListener);
  19. }
  20. @Override
  21. protected void onInactive() {
  22. //停止获取位置信息
  23. mLocationUtil.stop();
  24. }
  25. //创建一个位置监听器
  26. private LocationListener mLocationListener = new LocationListener() {
  27. @Override
  28. public void onReceiveLocation(Location location) {
  29. //接受到位置信息后,更新数据
  30. setValue(location);
  31. }
  32. };
  33. }

转换LiveData

map
  1. public class TestViewModel extends ViewModel {
  2. private MutableLiveData<Integer> mNumLiveData= new MutableLiveData<>();
  3. //通过Transformations.map()将Integer类型的值转换为String类型
  4. private LiveData<String> mStrLiveData = Transformations.map(mNumLiveData, new Function<Integer, String>() {
  5. @Override
  6. public String apply(Integer name) {
  7. return name + "";
  8. }
  9. });
  10. //observe这个,获取Integer类型的数据
  11. public MutableLiveData<Integer> getNumLiveData() {
  12. return mNumLiveData;
  13. }
  14. //observe这个,获取string类型的数据
  15. public LiveData<String> getStrLiveData() {
  16. return mStrLiveData;
  17. }
  18. }
switchMap
  1. public class TestViewModel extends ViewModel {
  2. private MutableLiveData<String> mutableLiveData1 = new MutableLiveData<>();
  3. private MutableLiveData<String> mutableLiveData2 = new MutableLiveData<>();
  4. private MutableLiveData<Boolean> liveDataSwitch = new MutableLiveData<>();
  5. LiveData transformedLiveData= Transformations.switchMap(liveDataSwitch, new Function<Boolean, LiveData<String>>() {
  6. @Override
  7. public LiveData<String> apply(Boolean input) {
  8. if (input) {
  9. return mutableLiveData1;
  10. } else {
  11. return mutableLiveData2;
  12. }
  13. }
  14. });
  15. public MutableLiveData<String> getMutableLiveData1() {
  16. return mutableLiveData1;
  17. }
  18. public MutableLiveData<String> getMutableLiveData2() {
  19. return mutableLiveData2;
  20. }
  21. public MutableLiveData<Boolean> getLiveDataSwitch() {
  22. return liveDataSwitch;
  23. }
  24. public MutableLiveData<Boolean> getTransformedLiveData() {
  25. return transformedLiveData;
  26. }
  27. }
  28. // 使用
  29. getTransformedLiveData().observe(this, new Observer<String>() {
  30. @Override
  31. public void onChanged(@Nullable final String s) {
  32. Log.d(TAG, "onChanged:" + s);
  33. }
  34. });
  35. getLiveDataSwitch().postValue(false);
  36. getMutableLiveData1().postValue("1111");
  37. getMutableLiveData2().postValue("2222");

当liveDataSwitch的值为true时返回mutableLiveData1,否则返回mutableLiveData2,可以用来切换监听的liveData

MediatorLiveData

MediatorLiveData继承自MutableLiveData,它可以将多个LiveData数据源集合起来,可以达到一个组件监听多个LiveData数据变化的目的。
当任何一个MutableLiveData数据发生变化时,MediatorLiveData都可以感知到。

  1. public class TestViewModel extends ViewModel {
  2. private MutableLiveData<String> mutableLiveData1 = new MutableLiveData<>();
  3. private MutableLiveData<String> mutableLiveData2 = new MutableLiveData<>();
  4. private MediatorLiveData liveDataMerger = new MediatorLiveData<String>();
  5. liveDataMerger.addSource(mutableLiveData1, new Observer() {
  6. @Override
  7. public void onChanged(@Nullable String str) {
  8. liveDataMerger.setValue(str)
  9. }
  10. });
  11. liveDataMerger.addSource(mutableLiveData2, new Observer() {
  12. @Override
  13. public void onChanged(@Nullable Object str) {
  14. liveDataMerger.setValue(str)
  15. }
  16. });
  17. public MutableLiveData<String> getLiveDataMerger() {
  18. return liveDataMerger;
  19. }
  20. public MutableLiveData<String> getMutableLiveData1() {
  21. return mutableLiveData1;
  22. }
  23. public MutableLiveData<Boolean> getMutableLiveData2() {
  24. return getMutableLiveData2;
  25. }
  26. }
  27. // 使用
  28. getLiveDataMerger().observe(this, new Observer<String>() {
  29. @Override
  30. public void onChanged(@Nullable final String s) {
  31. Log.d(TAG, "onChanged:" + s);
  32. }
  33. });
  34. getMutableLiveData1().postValue("1111");
  35. getMutableLiveData2().postValue("2222");

MediatorLiveData相比于LiveData,主要是多了以下两个方法:

源码

首先我们带着问题来看:

然后我们从使用方式入手,根据使用API来一步一步看一下内部是怎么实现的

LiveData

LiveData 包含两个用于添加数据观察者(Observer)的方法,分别是

两个方法的区别对于外部来说只在于是否提供了生命周期安全的保障

observe(LifecycleOwner , Observer)

observe(LifecycleOwner , Observer) 传入的 LifecycleOwner 参数意味着携带了 Lifecycle 对象,LiveData 内部就根据 Lifecycle 的生命周期事件的回调变化在合适的时机进行数据通知,并在 Lifecycle 对象处于 DESTROYED 状态时自动移除 Observer,这也是 LiveData 避免内存泄漏的最重要的一个点。

  1. @MainThread
  2. public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
  3. //限定只能在主线程调用 observe 方法
  4. assertMainThread("observe");
  5. //当 Lifecycle 已经处于 DESTROYED 状态时,此时进行 observe 是没有意义的,直接返回
  6. if (owner.getLifecycle().getCurrentState() == DESTROYED) {
  7. // ignore
  8. return;
  9. }
  10. //根据传入参数构建一个新的代理 Observer
  11. LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
  12. //将 observer 作为 key,wrapper 作为 value 进行存储
  13. //当 mObservers 不包含该 key 时,调用 putIfAbsent 会返回 null
  14. //当 mObservers 已包含该 key 时,调用 putIfAbsent 不会存储 key-value,并会返回之前保存的 value
  15. ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
  16. if (existing != null && !existing.isAttachedTo(owner)) {
  17. //走到此步,说明之前 LiveData 内部已经持有了 observer 对象,且该 observer 对象已经绑定了其它的 LifecycleOwner 对象
  18. //此时直接抛出异常
  19. throw new IllegalArgumentException("Cannot add the same observer"
  20. + " with different lifecycles");
  21. }
  22. if (existing != null) {
  23. //observer 之前已经传进来过了,此处直接返回
  24. return;
  25. }
  26. owner.getLifecycle().addObserver(wrapper);
  27. }

上面的代码使用到了 LifecycleBoundObserver,它是抽象类 ObserverWrapper 的实现类。

ObserverWrapper

ObserverWrapper 用于包装外部传进来的 Observer 对象,为子类定义好特定的抽象方法和共用逻辑,主要是提供了共用的状态分发函数。

  1. private abstract class ObserverWrapper {
  2. //外部传进来的对 LiveData 进行数据监听的 Observer
  3. final Observer<? super T> mObserver;
  4. //用于标记 mObserver 是否处于活跃状态
  5. boolean mActive;
  6. //用于标记 Observer 内最后一个被回调的 value 的新旧程度
  7. int mLastVersion = START_VERSION;
  8. ObserverWrapper(Observer<? super T> observer) {
  9. mObserver = observer;
  10. }
  11. //用于获取当前 Lifecycle 是否处于活跃状态
  12. abstract boolean shouldBeActive();
  13. //用于判断 mObserver 是否和 LifecycleOwner(即 Lifecycle)有绑定关系
  14. boolean isAttachedTo(LifecycleOwner owner) {
  15. return false;
  16. }
  17. //移除 mObserver
  18. void detachObserver() {
  19. }
  20. void activeStateChanged(boolean newActive) {
  21. if (newActive == mActive) {
  22. return;
  23. }
  24. // immediately set active state, so we'd never dispatch anything to inactive
  25. // owner
  26. mActive = newActive;
  27. //判断当前 LiveData 所有的 Observer 是否都处于非活跃状态
  28. boolean wasInactive = LiveData.this.mActiveCount == 0;
  29. //更新 LiveData 当前所有处于活跃状态的 Observer 的数量
  30. LiveData.this.mActiveCount += mActive ? 1 : -1;
  31. if (wasInactive && mActive) {
  32. //如果 LiveData 处于活跃状态的 Observer 数量从 0 变成了 1,
  33. //则回调 onActive 方法
  34. onActive();
  35. }
  36. if (LiveData.this.mActiveCount == 0 && !mActive) {
  37. //如果 LiveData 处于活跃状态的 Observer 数量从 1 变成了 0,
  38. //则回调 onInactive 方法
  39. onInactive();
  40. }
  41. if (mActive) {
  42. //如果 mObserver 变成了活跃状态,则向其回调新值
  43. dispatchingValue(this);
  44. }
  45. }
  46. }

主要是activeStateChanged(boolean newActive)方法:

所以ObserverWrapper#activeStateChanged主要做了两件事:

调用大概有三个地方:

ObserverWrapper 一共有两个子类:LifecycleBoundObserver 和 AlwaysActiveObserver,两者的差别就在于是否和生命周期相绑定。

LifecycleBoundObserver

LifecycleBoundObserver,它是抽象类 ObserverWrapper 的实现类,它也实现了 GenericLifecycleObserver或者LifecycleEventObserver 接口,从而可以收到 Lifecycle 的每次生命周期事件切换时的事件回调。

  1. class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
  2. @NonNull
  3. final LifecycleOwner mOwner;
  4. LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
  5. super(observer);
  6. mOwner = owner;
  7. }
  8. @Override
  9. boolean shouldBeActive() {
  10. //只有当 Lifecycle 的当前状态是 STARTED 或者 RESUMED 时
  11. //才认为 Lifecycle 是处于活跃状态
  12. return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
  13. }
  14. //LifecycleEventObserver 的实现方法
  15. //当 Lifecycle 的生命周期状态发生变化时就会调用此方法
  16. @Override
  17. public void onStateChanged(@NonNull LifecycleOwner source,
  18. @NonNull Lifecycle.Event event) {
  19. //如果 Lifecycle 已经处于 DESTROYED 状态了,则主动移除 mObserver
  20. //这就是 LiveData 可以避免内存泄露最重要的一个点
  21. if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
  22. removeObserver(mObserver);
  23. return;
  24. }
  25. activeStateChanged(shouldBeActive());
  26. }
  27. @Override
  28. boolean isAttachedTo(LifecycleOwner owner) {
  29. return mOwner == owner;
  30. }
  31. @Override
  32. void detachObserver() {
  33. //移除 mObserver
  34. mOwner.getLifecycle().removeObserver(this);
  35. }
  36. }

observeForever(Observer)

observeForever() 函数本身不会考虑外部所处的生命周期状态,只要数据发生变化时就会进行数据回调,因此 observeForever()函数是非生命周期安全的

  1. @MainThread
  2. public void observeForever(@NonNull Observer<? super T> observer) {
  3. //限定只能在主线程调用 observe 方法
  4. assertMainThread("observeForever");
  5. AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
  6. ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
  7. if (existing instanceof LiveData.LifecycleBoundObserver) {
  8. //会走到这一步,是因为之前已经先用该 observer 对象调用了 observe(LifecycleOwner,Observer)
  9. //这里直接抛出异常
  10. throw new IllegalArgumentException("Cannot add the same observer"
  11. + " with different lifecycles");
  12. }
  13. if (existing != null) {
  14. //如果之前已经添加过 observer 对象了的话,则直接返回
  15. return;
  16. }
  17. //主动触发 activeStateChanged 函数,因为当前 LiveData 可能已经被设置值了
  18. wrapper.activeStateChanged(true);
  19. }
AlwaysActiveObserver

AlwaysActiveObserver,它也是抽象类 ObserverWrapper 的实现类,其 shouldBeActive()返回值固定为 true,意味着只要有数据变化都会进行回调。
所以使用 observeForever() 函数一定要在过后主动移除 Observer,避免内存泄露和 NPE

  1. private class AlwaysActiveObserver extends ObserverWrapper {
  2. AlwaysActiveObserver(Observer<? super T> observer) {
  3. super(observer);
  4. }
  5. @Override
  6. boolean shouldBeActive() {
  7. //使其固定返回 true,则意味着只要有数据变化就都进行数据回调
  8. return true;
  9. }
  10. }

removeObserver

removeObserver 的方式一共有两种,逻辑都比较简单

  1. //移除指定的 Observer 对象
  2. @MainThread
  3. public void removeObserver(@NonNull final Observer<? super T> observer) {
  4. assertMainThread("removeObserver");
  5. ObserverWrapper removed = mObservers.remove(observer);
  6. if (removed == null) {
  7. return;
  8. }
  9. removed.detachObserver();
  10. removed.activeStateChanged(false);
  11. }
  12. //通过循环遍历移除所有和特定 LifecycleOwner 绑定的 Observer 对象
  13. @SuppressWarnings("WeakerAccess")
  14. @MainThread
  15. public void removeObservers(@NonNull final LifecycleOwner owner) {
  16. assertMainThread("removeObservers");
  17. for (Map.Entry<Observer<? super T>, ObserverWrapper> entry : mObservers) {
  18. if (entry.getValue().isAttachedTo(owner)) {
  19. removeObserver(entry.getKey());
  20. }
  21. }
  22. }

更新 LiveData 的值的方法一共有两个,分别是:

setValue()

  1. private volatile Object mData;
  2. private int mVersion;
  3. @MainThread
  4. protected void setValue(T value) {
  5. assertMainThread("setValue");
  6. //更新当前 value 的版本号,即 value 的新旧程度
  7. mVersion++;
  8. mData = value;
  9. dispatchingValue(null);
  10. }
dispatchingValue()

dispatchingValue() 这个被提到了很多次了

  1. //用于标记当前是否正处于向 mObservers 发布 value 的过程
  2. private boolean mDispatchingValue;
  3. //用于标记当前正在发布的 value 是否已经失效
  4. //在 value 还未向所有 Observer 发布完成的时候,新 value 已经到来,此时旧 value 就是处于失效状态
  5. @SuppressWarnings("FieldCanBeLocal")
  6. private boolean mDispatchInvalidated;
  7. //initiator 为 null 则说明需要遍历回调整个 mObservers
  8. //initiator 不为 null 则说明仅回调 initiator 本身
  9. @SuppressWarnings("WeakerAccess") /* synthetic access */
  10. void dispatchingValue(@Nullable ObserverWrapper initiator) {
  11. if (mDispatchingValue) {
  12. //如果 mDispatchingValue 为 true,说明当前正处于向 mObservers 发布 mData 的过程中
  13. //而 dispatchingValue 方法只会在主线程进行调用,所以会出现 mDispatchingValue 为 true 的情况
  14. //说明 Observer 的 onChanged 方法内部又主动向 LiveData setValue
  15. //则将 mDispatchInvalidated 置为 true,用于标明有新值到来,正在回调的值是已经过时的了
  16. mDispatchInvalidated = true;
  17. return;
  18. }
  19. //用于标记当前正处于向 mObservers 发布 mData 的过程中
  20. mDispatchingValue = true;
  21. do {
  22. mDispatchInvalidated = false;
  23. if (initiator != null) {
  24. considerNotify(initiator);
  25. initiator = null;
  26. } else {
  27. for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
  28. mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
  29. considerNotify(iterator.next().getValue());
  30. if (mDispatchInvalidated) {
  31. //如果 mDispatchInvalidated 为 true,则中断继续遍历过程
  32. //用新值来重新循环一遍
  33. break;
  34. }
  35. }
  36. }
  37. } while (mDispatchInvalidated);
  38. mDispatchingValue = false;
  39. }

这里,我有一个疑惑:
从逻辑上看 dispatchingValue() 函数只会在主线程进行调用,那么 dispatchingValue() 一定是会在执行完毕后才被再次执行,不存在多线程同时调用的情况,那么此时 mDispatchingValue 和 mDispatchInvalidated 两个变量就没有存在的必要了吧

considerNotify()
  1. private void considerNotify(ObserverWrapper observer) {
  2. //如果 observer 处于非活跃状态,则直接返回
  3. if (!observer.mActive) {
  4. return;
  5. }
  6. // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
  7. //
  8. // we still first check observer.active to keep it as the entrance for events. So even if
  9. // the observer moved to an active state, if we've not received that event, we better not
  10. // notify for a more predictable notification order.
  11. //此处判断主要是为了照顾 LifecycleBoundObserver
  12. //由于 Lifecycle 有可能状态值 State 已经切换到了非活跃状态,但 LifecycleBoundObserver 还未收到事件通知
  13. //所以为了避免意外情况,此处主动检查 observer 的活跃状态并判断是否需要更新其活跃状态
  14. if (!observer.shouldBeActive()) {
  15. observer.activeStateChanged(false);
  16. return;
  17. }
  18. //根据 observer 本部的 value 版本号 mLastVersion 来决定是否需要向其进行回调
  19. //为了避免重复向某个 observer 回调值,所以此处需要判断下
  20. if (observer.mLastVersion >= mVersion) {
  21. return;
  22. }
  23. observer.mLastVersion = mVersion;
  24. observer.mObserver.onChanged((T) mData);
  25. }

postValue()

postValue(T) 函数不限定调用者所在线程,不管是主线程还是子线程都可以调用,因此是存在多线程竞争的可能性的,postValue(T) 函数的重点旧在于需要理解其从子线程切换到主线程之间的状态变化

  1. @SuppressWarnings("WeakerAccess") /* synthetic access */
  2. final Object mDataLock = new Object();
  3. @SuppressWarnings("WeakerAccess") /* synthetic access */
  4. //mPendingData 的默认值
  5. //当 mPendingData 等于 NOT_SET 时说明当前 LiveData 没有值需要通过 postValue 回调
  6. static final Object NOT_SET = new Object();
  7. volatile Object mPendingData = NOT_SET;
  8. //用于在主线程对值进行回调
  9. private final Runnable mPostValueRunnable = new Runnable() {
  10. @SuppressWarnings("unchecked")
  11. @Override
  12. public void run() {
  13. Object newValue;
  14. synchronized (mDataLock) {
  15. //通过加锁可以确保 newValue 指向的是当前最新值
  16. newValue = mPendingData;
  17. //重置 mPendingData
  18. mPendingData = NOT_SET;
  19. }
  20. setValue((T) newValue);
  21. }
  22. };
  23. protected void postValue(T value) {
  24. boolean postTask;
  25. //加锁以保证 mPendingData 值能够一直指向最新值
  26. synchronized (mDataLock) {
  27. postTask = mPendingData == NOT_SET;
  28. mPendingData = value;
  29. }
  30. //如果 postTask 为 false,则说明当前有旧值需要通过 postValue 进行回调
  31. //因为 postValue 可以在子线程调用,而 Observer 的 onChanged(value) 方法肯定是要在主线程被调用
  32. //从子线程切到主线程之间是有段时间间隔的
  33. //等到 mPostValueRunnable 真正执行时让其直接发送最新值 mPendingData 即可,所以此处直接返回
  34. if (!postTask) {
  35. return;
  36. }
  37. //向主线程发送一个 runnable,主要是为了在子线程调用 postValue,在主线程进行值回调
  38. ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
  39. }

调用线程:

主线程:

所以当多个线程同时调用,在postTask为false,直接return的时候,其实是会导致丢值的。在单个线程连续调用的时候,也会导致这个问题,为什么?因为调用Handler#post(),会延迟调用,所以也会导致这个问题。

小结

MutableLiveData

LiveData 的 setValue() 和 postValue() 方法的访问权限都是 protected,因此我们在日常开发中基本都是使用其子类

MutableLiveData 的源码很简单,只是将 setValue() 和 postValue() 方法的访问权限提升为了 public,从而让外部可以直接调用这两个方法:

  1. public class MutableLiveData<T> extends LiveData<T> {
  2. /**
  3. * Creates a MutableLiveData initialized with the given {@code value}.
  4. *
  5. * @param value initial value
  6. */
  7. public MutableLiveData(T value) {
  8. super(value);
  9. }
  10. /**
  11. * Creates a MutableLiveData with no value assigned to it.
  12. */
  13. public MutableLiveData() {
  14. super();
  15. }
  16. @Override
  17. public void postValue(T value) {
  18. super.postValue(value);
  19. }
  20. @Override
  21. public void setValue(T value) {
  22. super.setValue(value);
  23. }
  24. }

MediatorLiveData

MediatorLiveData 是 MutableLiveData 的子类,可以添加多个LiveData数据源,监听这个多个LiveData,在他们的Observer回调的时候,调用MediatorLiveData自己的setValue来通知自己的Observer,具体例子可以看上面关于MediatorLiveData的使用例子

addSource
  1. private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();
  2. @MainThread
  3. public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
  4. Source<S> e = new Source<>(source, onChanged);
  5. Source<?> existing = mSources.putIfAbsent(source, e);
  6. if (existing != null && existing.mObserver != onChanged) {
  7. //走到这一步,说明之前已经传进来过同个 source 对象
  8. //但当时传的 Observer 对象与本地传递的 Observer 对象不是同一个
  9. //直接抛出异常
  10. throw new IllegalArgumentException(
  11. "This source was already added with the different observer");
  12. }
  13. if (existing != null) {
  14. //走到此步,说明之间已经用相同的 source 和 onChanged 对象调用过 addSource 方法
  15. //所以直接返回
  16. return;
  17. }
  18. //如果 MediatorLiveData 当前有处于活跃状态的 Observer 对其进行监听
  19. //则调用 Source 对象的 plug() 函数
  20. if (hasActiveObservers()) {
  21. e.plug();
  22. }
  23. }

MediatorLiveData的源码其实很类似于LiveData,最重要的是增加了addSource()和removeSource():

removeSource()
  1. //移除对数据源的监听行为
  2. @MainThread
  3. public <S> void removeSource(@NonNull LiveData<S> toRemote) {
  4. Source<?> source = mSources.remove(toRemote);
  5. if (source != null) {
  6. source.unplug();
  7. }
  8. }

代码很简单:

Source
  1. private static class Source<V> implements Observer<V> {
  2. final LiveData<V> mLiveData;
  3. final Observer<? super V> mObserver;
  4. int mVersion = START_VERSION;
  5. Source(LiveData<V> liveData, final Observer<? super V> observer) {
  6. mLiveData = liveData;
  7. mObserver = observer;
  8. }
  9. //对外部数据源 mLiveData 进行监听
  10. void plug() {
  11. mLiveData.observeForever(this);
  12. }
  13. //移除对外部数据源 mLiveData 的监听
  14. void unplug() {
  15. mLiveData.removeObserver(this);
  16. }
  17. @Override
  18. public void onChanged(@Nullable V v) {
  19. if (mVersion != mLiveData.getVersion()) {
  20. mVersion = mLiveData.getVersion();
  21. mObserver.onChanged(v);
  22. }
  23. }
  24. }

所以虽然提供了unplug(),但是如果使用者没有调用呢,怎么能保证unplug()一定被调用呢?

MediatorLiveData复写了LiveDataonActive()onInactive()

  1. @CallSuper
  2. @Override
  3. protected void onActive() {
  4. for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
  5. source.getValue().plug();
  6. }
  7. }
  8. @CallSuper
  9. @Override
  10. protected void onInactive() {
  11. for (Map.Entry<LiveData<?>, Source<?>> source : mSources) {
  12. source.getValue().unplug();
  13. }
  14. }
小结

再说一下用法,根据用法我们来理解一下:

  • MediatorLiveData#addSource(LiveData, Observer)
  • MediatorLiveData#addSource(LiveData, Observer)
  • MediatorLiveData#addSource(LiveData, Observer)
  • MediatorLiveData#Observer(Observer)

为了描述简单,我们说MediatorLiveData为父LiveData,addSource添加的LiveData为子LiveData:

Transformations

Transformations 类是 lifecycle-livedata 库提供的一个工具类型的方法类,提供了三个静态方法用于简化对 MediatorLiveData 的使用,这里再来依次介绍下:

map

map(LiveData , Function) 函数用于简化向 MediatorLiveData 添加数据源的过程。大多数情况下,我们在使用 MediatorLiveData 时就是先将数据源类型 X 转换我们的目标数据类型 Y,然后再通过 setValue(Y) 进行数据回调。map 函数将这个数据类型转换过程抽象为了接口 Function,将 setValue(Y) 过程隐藏在了 map 函数内部

  1. @MainThread
  2. @NonNull
  3. public static <X, Y> LiveData<Y> map(
  4. @NonNull LiveData<X> source,
  5. @NonNull final Function<X, Y> mapFunction) {
  6. final MediatorLiveData<Y> result = new MediatorLiveData<>();
  7. result.addSource(source, new Observer<X>() {
  8. @Override
  9. public void onChanged(@Nullable X x) {
  10. result.setValue(mapFunction.apply(x));
  11. }
  12. });
  13. return result;
  14. }
  15. public interface Function<I, O> {
  16. /**
  17. * Applies this function to the given input.
  18. *
  19. * @param input the input
  20. * @return the function result.
  21. */
  22. O apply(I input);
  23. }
switchMap

switchMap,可以用来切换不同的子LiveData

  1. @MainThread
  2. @NonNull
  3. public static <X, Y> LiveData<Y> switchMap(
  4. @NonNull LiveData<X> source,
  5. @NonNull final Function<X, LiveData<Y>> switchMapFunction) {
  6. final MediatorLiveData<Y> result = new MediatorLiveData<>();
  7. //先内部构建一个 MediatorLiveData,然后将 source 作为其数据源
  8. result.addSource(source, new Observer<X>() {
  9. //缓存每次的请求结果
  10. LiveData<Y> mSource;
  11. @Override
  12. public void onChanged(@Nullable X x) {
  13. //触发外界根据请求值 x 获得 LiveData 结果值的逻辑
  14. //对应上面例子的 getUsersWithNameLiveData 方法
  15. //这个过程是惰性的,即只有数据源 source 发生了变化才会触发请求
  16. LiveData<Y> newLiveData = switchMapFunction.apply(x);
  17. if (mSource == newLiveData) {
  18. //如果 newLiveData 之前已经拿到了,则不必重复监听其回调结果
  19. //直接返回即可
  20. return;
  21. }
  22. if (mSource != null) {
  23. //新值到来,移除对旧值的监听
  24. result.removeSource(mSource);
  25. }
  26. mSource = newLiveData;
  27. if (mSource != null) {
  28. result.addSource(mSource, new Observer<Y>() {
  29. @Override
  30. public void onChanged(@Nullable Y y) {
  31. //等到拿到了getUsersWithNameLiveData 的请求结果后
  32. //就将结果值回调出去
  33. result.setValue(y);
  34. }
  35. });
  36. }
  37. }
  38. });
  39. return result;
  40. }
distinctUntilChanged

distinctUntilChanged() 函数用于过滤掉连续重复的回调值,只有本次的回调结果和上次不一致,本次的回调值才被认为是有效的

  1. @MainThread
  2. @NonNull
  3. public static <X> LiveData<X> distinctUntilChanged(@NonNull LiveData<X> source) {
  4. final MediatorLiveData<X> outputLiveData = new MediatorLiveData<>();
  5. outputLiveData.addSource(source, new Observer<X>() {
  6. //用于是否是第一次收到回调值
  7. boolean mFirstTime = true;
  8. @Override
  9. public void onChanged(X currentValue) {
  10. final X previousValue = outputLiveData.getValue();
  11. //等式成立的条件一共有三种,满足其一即可
  12. //1. 是第一次收到回调值,即 mFirstTime 为 true
  13. //2. 上次的回调值为 null,本次的回调值不为 null
  14. //3. 上次的回调值不为 null,且与本次的回调值不相等
  15. if (mFirstTime
  16. || (previousValue == null && currentValue != null)
  17. || (previousValue != null && !previousValue.equals(currentValue))) {
  18. mFirstTime = false;
  19. outputLiveData.setValue(currentValue);
  20. }
  21. }
  22. });
  23. return outputLiveData;
  24. }
小结

总结

感觉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

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注