Jetpack学习之 LiveData

})

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()

// 1

liveDataSwitch = MutableLiveData()

// 如果是true,选择监听1,否则监听2

val 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()

val mutableLiveData2 = MutableLiveData()

// 创建一个用于合并数据源的LiveData

val liveDataManager = MediatorLiveData()

// 添加数据 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() {

companion object {

private const val TAG = “ExtStringLiveData”

private var sInstance: ExtStringLiveData? = null

@MainThread

fun 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 的同学肯定就知道了其中的奥秘。我们来看看它的源码吧:

@MainThread

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

assertMainThread(“observe”);

// 1

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

return;

}

// 2

LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);

// 3

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;

}

// 4

owner.getLifecycle().addObserver(wrapper);

}

注释1:如果当前声明周期是 DESTORYED, 则拒绝注册

注释2:新建一个 LifecycleBoundObserver 实例,并传入相应参数

注释3:mObservers 的类型是 SafeIterableMap<Observer<? super T>, ObserverWrapper>mObservers,key是观察者,value是注释2中创建的对象。

在这个map中的putIfAbsentput 是有区别的,如果传入的 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;

@Override

boolean shouldBeActive() {

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

}

@Override

public 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;

// 1

activeStateChanged(shouldBeActive());

currentState = mOwner.getLifecycle().getCurrentState();

}

}

@Override

boolean isAttachedTo(LifecycleOwner owner) {

return mOwner == owner;

}

@Override

void 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) {

// 1

dispatchingValue(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;

// 1

observer.mObserver.onChanged((T) mData);

}

即使是到了这里,也会一直在判断当前组件的状态,非常严格呢。

如果所有更新条件都满足,则会调用 Observer 的 onChanged() , 也就从这里回调出去了~

3.3 postValue 方法


我们来看看调用 postValue() / setValue() 之后,LiveData 做了什么事情, 这里以 postValue 为例,来看看代码~

protected void postValue(T value) {

boolean postTask;

最后

我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。

其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。

不断奔跑,你就知道学习的意义所在!


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
)3.3 postValue 方法


我们来看看调用 postValue() / setValue() 之后,LiveData 做了什么事情, 这里以 postValue 为例,来看看代码~

protected void postValue(T value) {

boolean postTask;

最后

我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。

其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。

不断奔跑,你就知道学习的意义所在!

[外链图片转存中…(img-isVmFESE-1715666038450)]

[外链图片转存中…(img-obQRAOnr-1715666038453)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值