})
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 就打印不出来了。
=======================================================================
因为组件都是通过调用 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中的putIfAbsent
和 put
是有区别的,如果传入的 key 存在,就返回value,而不替换,如果 key 不存在,则添加进去,并返回null。
注释4:如果注释3的map中没有数据, 则调用 Lifecycle.addObserver
,传入的是 LivecycleBoundObserver
。 看来这个类比较重要,我们有必要去了解它的构造和作用。
来看看 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()
, 也就从这里回调出去了~
我们来看看调用 postValue()
/ setValue()
之后,LiveData 做了什么事情, 这里以 postValue 为例,来看看代码~
protected void postValue(T value) {
boolean postTask;
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
) {
boolean postTask;
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-lB7tOp0b-1715757440990)]
[外链图片转存中…(img-YnjvLeXs-1715757440991)]
[外链图片转存中…(img-7W0jII2Y-1715757440993)]
[外链图片转存中…(img-YxBE45Jt-1715757440994)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!