Jetpack学习之 LiveData,Context都没弄明白凭什么拿高薪

  • 除了使用 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()

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

// 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。

结语

  • 现在随着短视频,抖音,快手的流行NDK模块开发也显得越发重要,需要这块人才的企业也越来越多,随之学习这块的人也变多了,音视频的开发,往往是比较难的,而这个比较难的技术就是NDK里面的技术。
  • 音视频/高清大图片/人工智能/直播/抖音等等这年与用户最紧密,与我们生活最相关的技术一直都在寻找最终的技术落地平台,以前是windows系统,而现在则是移动系统了,移动系统中又是以Android占比绝大部分为前提,所以AndroidNDK技术已经是我们必备技能了。
  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。

有需要的小伙伴可以私信我免费分享给你或者点击下面链接自行领取

Android学习PDF+架构视频+面试文档+源码笔记

技术已经是我们必备技能了。

  • 要学习好NDK,其中的关于C/C++,jni,Linux基础都是需要学习的,除此之外,音视频的编解码技术,流媒体协议,ffmpeg这些都是音视频开发必备技能,而且
  • OpenCV/OpenGl/这些又是图像处理必备知识,下面这些我都是当年自己搜集的资料和做的一些图,因为当年我就感觉视频这块会是一个大的趋势。所以提前做了一些准备。现在拿出来分享给大家。

有需要的小伙伴可以私信我免费分享给你或者点击下面链接自行领取

Android学习PDF+架构视频+面试文档+源码笔记

[外链图片转存中…(img-s99DVo1Q-1643790883123)]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值