公司网站做的比较好/推广软件哪个好
LiveData 是 Google 推荐的基于观察者的数据持有者,可以认为是一个轻量级的RxJava。
一般来说不会单独使用,会和其他组件一起搭配,最常用的就是 ViewModel 了。
目录
- 1. 概述
- 1.1 什么是LiveData
- 1.2 为什么使用LiveData
- 2. 使用
- 2.1 基本用法
- 2.2 更改 LiveData 中的数据
- 2.2.1 Transformations.map 方法
- 2.2.2 Transformations.switchMap 方法
- 2.2.3 MediatorLiveData合并数据源
- 2.2.4 自定义LiveData
- 3. 原理
- 3.1 LiveData 如何观察生命周期变化
- 3.2 LiveData 的 observe 方法回调
- 3.3 postValue 方法
- 3.4 总结
- 参考文章
1. 概述
1.1 什么是LiveData
官方定义:
LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData具有生命周期感知能
力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可
确保 LiveData仅更新处于活跃生命周期状态的应用组件观察者。
简单可以理解为一个 Observable
,同时能够感知生命周期。
如果搭配ViewModel,那么 ViewModel 就是 LiveData 的数据源,当数据更新后, LiveData 就会通知它的所有观察者。 与 RxJava 的方法不同的是, LiveData 并不是通知所有观察者,他只会通知处于 Active 状态的观察者,如果一个观察者处于 Paused 状态或 Destroyed 状态,那么它将不会受到通知。
1.2 为什么使用LiveData
- 解耦
- 避免内存泄漏
Activity、Service、Fragment可以安全的观察LiveData对象,而且不用在 onPaused 或者 onDestroy 方法中去解订阅。
一旦观察者恢复 resumed 状态, 它将会重新收到 LiveData 的最新数据。
2. 使用
这里省去导入流程,可以看 Jetpack学习之 Lifecycle
2.1 基本用法
LiveData 是一个抽象类, 它有一个比较简单又常用的实现类:MutableLiveData
, 这里举个栗子:
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val mutableLiveData = MutableLiveData<String>()// 1mutableLiveData.observe(this, Observer { Log.d(TAG, "onChanged: $it")})// 2mutableLiveData.postValue("Hi Noel~")}
}
注释1:observe()
有两个参数,分别是 LifecycleOwner
和 Observer<T>
也就是被观察者。
Kotlin代码的lambda表达式省略掉了其实现方法体,也就是 onChanged(@Nullable final String s)
方法,他能够在数据变化时,回调这个方法
注释2:postValue()
会在主线程更新数据,这样就会得到打印的结果,如下所示:
这里需要注意的是:
- 将更新界面的LiveData对象存储在ViewModel中,而不是将其存储在Activity或Fragment中:
(1)避免Activity或Fragment过于庞大,分离 ui 和数据
(2)将LiveData实例与特定Activity实例分离开,使LiveData对象在配置更改后继续存在 - 在onCreate方法中开始观察LiveData对象
不要在onResume方法中进行调用observe()
,因为会出现多次调用的问题。
确保Activity或Fragment变为活跃状态后具有可以立即显示的数据,因为应用组件处于STARTED 状态,就会从它正在观察的LiveData
对象接收最新值 - 当组件处于DESTROY状态时会自动取消订阅
- 除了使用
postValue()
,还可以使用setValue()
,区别是后者必须在主线程调用。如果需要在子线程中更新 LiveData, 可以使用 postValue 方法。
2.2 更改 LiveData 中的数据
2.2.1 Transformations.map 方法
和 RxJava 一样,我们可以对数据分发到指定对象之前,给它map一下,转化成另一种数据,比如下面代码,LiveData 原数据是 Int 型, 通过 map 转化成 String 类型(或则任何数据):
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val mutableLiveData = MutableLiveData<Int>()mutableLiveData.observe(this, Observer {Log.d(TAG, "onChanged1: $it")})val transformationsLiveData = Transformations.map(mutableLiveData) { input ->("$input go")}transformationsLiveData.observe(this, Observer {Log.d(TAG, "obChanged2: $it")})mutableLiveData.postValue(1)}
2.2.2 Transformations.switchMap 方法
和 map 不同, switchMap返回的结果必须是一个 LiveData
数据,而且它可以通过一个 Boolean 值来选择监听对象
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)mutableLiveData1 = MutableLiveData()mutableLiveData2 = MutableLiveData()// 1liveDataSwitch = MutableLiveData()// 如果是true,选择监听1,否则监听2val transformedLiveData = Transformations.switchMap(liveDataSwitch) {if (it) mutableLiveData1 else mutableLiveData2}transformedLiveData.observe(this, Observer {Log.d(TAG, "onChanged: $it")})liveDataSwitch.postValue(false)mutableLiveData1.postValue("noel")mutableLiveData2.postValue("bye")}
注释1:创建一个 MutableLiveData<Boolean>
来控制切换并复制给 liveDataSwitch
当 liveDataSwitch 的值为 true 时, 返回 mutableLiveData1, 否则返回 mutableLiveData2
这样最终输出的结果为2
2.2.3 MediatorLiveData合并数据源
MediatorLiveData
继承自 MutableLiveData, 它的作用是可以收集多个 LiveData。 如果其中一个 LiveData 数据源发生变化,那么也会通知到 MediatorLiveData
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val mutableLiveData1 = MutableLiveData<String>()val mutableLiveData2 = MutableLiveData<String>()// 创建一个用于合并数据源的LiveDataval liveDataManager = MediatorLiveData<String>()// 添加数据 LiveData1, 并监听其变化liveDataManager.addSource(mutableLiveData1) {Log.d(TAG, "onChanged 1: $it")}// 添加数据 LiveData2, 并监听其变化liveDataManager.addSource(mutableLiveData2) {Log.d(TAG, "onChanged 2: $it")}liveDataManager.observe(this, Observer {Log.d(TAG, "onChanged Data: $it")})mutableLiveData1.postValue("i always like u")liveDataManager.postValue("thank u")}
打印结果:
2.2.4 自定义LiveData
我们可以自定义一个 LiveData, 因为会有观察者来观察这个 LiveData, 所以观察者处于 STARTED 或者 RESUMED 时,LiveData 将会处于 Activity状态,这个时候通过实现 onActive()
/ onInactive()
来通知观察者。
下面是个例子,我们设定一个可以变化的数据类:
class ExtStringLiveData private constructor() : LiveData<String>() {companion object {private const val TAG = "ExtStringLiveData"private var sInstance: ExtStringLiveData? = null@MainThreadfun get(): ExtStringLiveData? {if (sInstance == null) {sInstance = ExtStringLiveData()}return sInstance}}// 观察者处于活跃状态, 则通知它override fun onActive() {Log.d(TAG, "onActive")// 这里的数据是写死的, 在实际项目中, 可以以监听器不断输出数据value = "if u find me again, i will with u again"}override fun onInactive() {Log.d(TAG, "onInactive")// 这里的数据是写死的, 在实际项目中, 可以以监听器不断输出数据// 在这之后, 就不会再想观察者发送数据直到观察者恢复active状态, 所以这一里在更改数据就不会通知了value = "because I'm starting to regret it"}
}
然后在 MainActivity 去监听它:
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)ExtStringLiveData.get()?.observe(this, Observer {Log.d(TAG, it)})}
打印结果为:
而在 LiveData 的 onInactive()
中更改的string数据, MainActivity 就打印不出来了。
3. 原理
3.1 LiveData 如何观察生命周期变化
因为组件都是通过调用 LiveData.observe(LifecycleOwner, Observer<? super T>)
进行监听,所以了解 Livecycle
的同学肯定就知道了其中的奥秘。我们来看看它的源码吧:
@MainThreadpublic void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {assertMainThread("observe");// 1if (owner.getLifecycle().getCurrentState() == DESTROYED) {return;}// 2LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);// 3ObserverWrapper 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;}// 4owner.getLifecycle().addObserver(wrapper);}
注释1:如果当前声明周期是 DESTORYED
, 则拒绝注册
注释2:新建一个 LifecycleBoundObserver
实例,并传入相应参数
注释3:mObservers 的类型是 SafeIterableMap<Observer<? super T>, ObserverWrapper>mObservers
,key是观察者,value是注释2中创建的对象。
在这个map中的putIfAbsent
和 put
是有区别的,如果传入的 key 存在,就返回value,而不替换,如果 key 不存在,则添加进去,并返回null。
注释4:如果注释3的map中没有数据, 则调用 Lifecycle.addObserver
,传入的是 LivecycleBoundObserver
。 看来这个类比较重要,我们有必要去了解它的构造和作用。
3.2 LiveData 的 observe 方法回调
来看看 LivecycleBoundObserver
,它是 LiveData 的内部类:
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {@NonNull final LifecycleOwner mOwner;...@Overrideboolean shouldBeActive() {return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);}@Overridepublic void onStateChanged(@NonNull LifecycleOwner source,@NonNull Lifecycle.Event event) {Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();if (currentState == DESTROYED) {removeObserver(mObserver);return;}Lifecycle.State prevState = null;while (prevState != currentState) {prevState = currentState;// 1activeStateChanged(shouldBeActive());currentState = mOwner.getLifecycle().getCurrentState();}}@Overrideboolean isAttachedTo(LifecycleOwner owner) {return mOwner == owner;}@Overridevoid detachObserver() {mOwner.getLifecycle().removeObserver(this);}}
该类继承了 ObserverWrapper
类,重写了 shouldBeActive()
方法, 它的作用是用来判断当前传入的组件是否是 Active的, Active状态包括 STARTED 、 RESUMED
该类还实现了 LifecycleEventObserver
接口,当组件状态发生变化的时候, 会调用 onStateChanged()
,当组件处于 DESTORYED 状态是,会调用 removeObserver()
来移除 observer。
这也就是为什么,LiveData 不会给那些 Inactive 的组件发通知。
注释1: 调用父类的 activeStateChanged()
,我们来看看父类:
private abstract class ObserverWrapper {final Observer<? super T> mObserver;boolean mActive;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;}mActive = newActive;changeActiveCounter(mActive ? 1 : -1);if (mActive) {// 1dispatchingValue(this);}}}
ObserverWrapper
是一个抽象类,它包装了一个 Observer, activeStateChanged
会看 传进来的状态是否和此前状态是否相同,不同则,则执行 changeActiveCounter()
,来更新一下当前LiveData 观察者的活跃与非活跃的数量, 来决定调用 onActive()
或 onInactive()
其次,如果当前是 Active 状态,则调用注释1的 dispatchingValue()
方法
void dispatchingValue(@Nullable ObserverWrapper initiator) {// 如果当前正在分发, 则返回if (mDispatchingValue) {// 表示分发无效mDispatchInvalidated = true;return;}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) {break;}}}} while (mDispatchInvalidated);// 标记不处于分发状态mDispatchingValue = false;}
如果当前处于可分发状态, 则会调用 considerNotify()
方法:
private void considerNotify(ObserverWrapper observer) {if (!observer.mActive) {return;}if (!observer.shouldBeActive()) {observer.activeStateChanged(false);return;}if (observer.mLastVersion >= mVersion) {return;}observer.mLastVersion = mVersion;// 1observer.mObserver.onChanged((T) mData);}
即使是到了这里,也会一直在判断当前组件的状态,非常严格呢。
如果所有更新条件都满足,则会调用 Observer 的 onChanged()
, 也就从这里回调出去了~
3.3 postValue 方法
我们来看看调用 postValue()
/ setValue()
之后,LiveData 做了什么事情, 这里以 postValue 为例,来看看代码~
protected void postValue(T value) {boolean postTask;synchronized (mDataLock) {postTask = mPendingData == NOT_SET;mPendingData = value;}if (!postTask) {return;}// 1ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);}private final Runnable mPostValueRunnable = new Runnable() {@SuppressWarnings("unchecked")@Overridepublic void run() {Object newValue;synchronized (mDataLock) {newValue = mPendingData;mPendingData = NOT_SET;}// 2setValue((T) newValue);}};// 3@MainThreadprotected void setValue(T value) {assertMainThread("setValue");mVersion++;mData = value;// 4dispatchingValue(null);}
注释1、2:做一个线程切换,切换到主线程中,并用线程安全的 synchronized()
注释3:确定当前线程是主线程,在非主线程中直接调用该方法会crash
注释4: 调用 dispatchingValue
,之后就是 considerNotify()
来通知观察者啦~
3.4 总结
LiveData
基于观察者模式实现和LifecyclerOwner
绑定后能感知生命周期- 只有处于活跃状态的 Owne r才会接收到数据变化的通知,Owner从非活跃状态变为活跃状态,会接收到新的数据通知
- Owner进入DESTROY状态会自动 remove Observer,不会担心内存泄露问题,如果希望一直接收到通知,可以使用
observeForever()
方法 - 主线程使用
setValue()
、工作线程使用postValue()
进行数据更新
参考文章
《Android进阶指北》Android Jetpack架构组件
LiveData官方文档