AndroidJetpack Livedata最详尽的使用场景分析


LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力

如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。

您可以注册与实现 LifecycleOwner 接口的对象配对的观察者。有了这种关系,当相应的 Lifecycle 对象的状态变为 DESTROYED 时,便可移除此观察者。这对于 Activity 和 Fragment 特别有用,因为它们可以放心地观察 LiveData 对象,而不必担心泄露

LiveData 优势


  1. 数据符合页面状态

  2. 不会发生内存泄露

  3. 不会因 activity 停止而导致崩溃

  4. 不再需要手动处理生命周期

  5. 数据始终保持最新状态

  6. 可以用来做资源共享

Livedata 使用


一般来说我们会在 ViewModel 中创建 Livedata 对象,然后再 Activity/Fragment 的 onCreate 中注册 Livedata 监听(因为在 onStart 和 onResume 中进行监听可能会有冗余调用)

Livedata 简单使用

仍然还是用我们倒计时的例子,在 Viewmodel 中开始一个 2000s 的倒计时,然后通过 Livedata 回调给 Activity 进行更新界面,代码:

  1. viewmodel 代码

class CountDownModel : ViewModel() {

val countDownLivedata = MutableLiveData()

private var remainSecond = 2000//剩余秒数

init {

val countDown = object : CountDownTimer(2000 * 1000, 1000) {

override fun onTick(millisUntilFinished: Long) {

remainSecond–

countDownLivedata.postValue(“剩余:${remainSecond} 秒”)

}

override fun onFinish() {

countDownLivedata.postValue(“倒计时结束”)

}

}

countDown.start()

}

}

复制代码

  1. activity 中观察数据更新 ui 代码

val countDownModel: CountDownModel by viewModels {

ViewModelProvider.NewInstanceFactory()

}

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_count_down)

countDownModel.countDownLivedata.observe(this, object : Observer {

override fun onChanged(value: String?) {

value?.let {

tv_countdown_remainsecond.text = it

}

}

})

}

复制代码

  1. 效果图

image

使用全局 Livedata 在多个视图监听状态

本例实现的 demo 效果是,创建一个全局的倒计时,然后在 Activity 中添加两个按钮,点击后可以切换 FragmentA 和 FragmentB。然后我们通过全局的自定义 LiveData 单例实现数据监听,切换 Fragment 后 Fragment 页面上会展示倒计时的剩余秒数

代码:

  1. 全局自定义 Livedata 代码

class GlobalLivedata : LiveData() {

val coundManager = CountDownManager()

val listener = object : OnDataChangeListener {

override fun change(data: String) {

postValue(data)

}

}

override fun onActive() {

super.onActive()

coundManager.setListener(listener)

}

override fun onInactive() {

super.onInactive()

coundManager.removeListener(listener)

}

companion object {

private lateinit var globalData: GlobalLivedata

fun getInstance(): GlobalLivedata {

globalData = if (::globalData.isInitialized) globalData else GlobalLivedata()

return globalData

}

}

}

复制代码

  1. 倒计时器代码较长只粘贴一部分,有兴趣可以到 github 去查看完整代码

private val listeners = mutableListOf()

init {

val countDown = object : CountDownTimer(2000 * 1000, 1000) {

override fun onTick(millisUntilFinished: Long) {

remainSecond–

callback(“剩余:${remainSecond} 秒”)

}

override fun onFinish() {

callback(“倒计时结束”)

}

}

countDown.start()

}

/**

  • 循环遍历回调消息

*/

private fun callback(msg:String) {

for (listener in listeners){

listener.change(msg)

}

}

复制代码

  1. FragmentA、FragmentB 中监听倒计时状态

GlobalLivedata.getInstance().observe(viewLifecycleOwner,

{ t ->

inflate.findViewById(R.id.tv_fragmentA).text = “fragmenta:${t}”

})

复制代码

GlobalLivedata.getInstance().observe(viewLifecycleOwner,

{ t ->

inflate.findViewById(R.id.tv_fragmentB).text = “fragmentb:${t}”

})

复制代码

  1. 最终效果

image

最终效果,当我们切换 Fragment 的时候两个 Fragment 显示的秒数是一致的,其实即使我们马上启动一个新 activity 去查看剩余秒数也是一样的,有兴趣的朋友可以下载 git 代码自己尝试

对 Livedata 进行转换

map 和 switchMap 两个方法可以对已有的 Livedata 进行转换得到新的 Livedata

Transformation.map

在 activity 中观察 viewmodel 中的数据更新,当点击 activity 中按钮的时候会调用 viewmodel.sendData 方法发送数据,然后发送的数据会做一定的转换给 activity,然后 activity 打印日志展示

直接看代码吧:

  1. 创建 viewmodel,model 中创建 Livedata

class TransMapViewModel: ViewModel() {

fun sendData() {

userLivedata.value=User(“李白”,1200)//对userLivedata进行复制

}

val userLivedata =MutableLiveData()

val mapLiveData = Transformations.map(userLivedata){

“${it.name} : ${it.age}”//这里可以返回任意类型的数据

}

}

data class User(var name:String,var age:Int)

复制代码

代码中 mapLiveData 是对 userLivedata 进行转换得到的,所以当我们调用 sendData 方法更新 userLivedata 中的方法时,mapLiveData 的回调也会触发

  1. 在 activity 中观察 mapLiveData 并点击按钮发送小数据

mapViewModel.mapLiveData.observe(this,{

logEE(it)

tv_map.text=it

})

btn_map.setOnClickListener {

mapViewModel.sendData()

}

复制代码

Transformation.switchMap

本例中我们实现如下逻辑:

在 activity 中观察 viewmodel 中的数据更新,当点击 activity 中按钮的时候会调用 viewmodel.sendData 方法发送数据,然后发送的数据会做一定的转换给 activity,然后 activity 打印日志展示

  1. viewmodel 中代码

class SwitchMapViewModel : ViewModel() {

fun sendData() {

userLivedata.value = SwitchUser(“李白”, 1200)

}

private val userLivedata = MutableLiveData()

val mapLiveData = Transformations.switchMap(userLivedata) {

changeUser(it!!)

}

private fun changeUser(it: SwitchUser): LiveData {

return MutableLiveData(“${it.name} 的名字杜甫知道”)

}

}

data class SwitchUser(var name: String, var age: Int)

复制代码

  1. 调用部分代码

model.mapLiveData.observe(this, {

logEE(it)

})

btn_switchmap.setOnClickListener {

model.sendData()

}

复制代码

合并两个 Livedata(MediatorLiveData)

想象这样一个场景,您的 app 里面有一个评论列表的功能,可以对列表内容进行点赞。每一个点赞都是一个异步任误,你的产品需求并不想让用户点太多赞,比如一分钟点赞数量不能超过 10 次,这种场景就很适合用 Livedata 的合并功能

我们就不模拟这么复杂的场景了,我们的例子做这样一个事情:

界面上有两个按钮,点一次相当于点赞一次,我们点击十次按钮就在界面上展示文字提示用户已经点击了十次数据。

代码展示:

1.model 代码

class MeditorLiveViewModel : ViewModel() {

var count =0//计数字段

fun setData1(name: String) {

liveData1.value = name

}

fun setData2(age: Int) {

liveData2.value = age

}

private val liveData1 = MutableLiveData()

private val liveData2 = MutableLiveData()

val liveCombind = MediatorLiveData()

init {

liveCombind.addSource(liveData1) {

increase()

}

liveCombind.addSource(liveData2) {

increase()

}

}

private fun increase() {

count++

if(count==10){

liveCombind.value=“安安安安卓同学,您已经点击 ${count}次,再点我也不跟你玩了,收手吧。。。”

}

}

}

复制代码

先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以扫码领取!!!!

建议

当我们出去找工作,或者准备找工作的时候,我们一定要想,我面试的目标是什么,我自己的技术栈有哪些,近期能掌握的有哪些,我的哪些短板 ,列出来,有计划的去完成,别看前两天掘金一些大佬在驳来驳去 ,他们的观点是他们的,不要因为他们的观点,膨胀了自己,影响自己的学习节奏。基础很大程度决定你自己技术层次的厚度,你再熟练框架也好,也会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

Android高级技术大纲

面试资料整理

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

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

己的学习节奏。基础很大程度决定你自己技术层次的厚度,你再熟练框架也好,也会比你便宜的,性价比高的替代,很现实的问题但也要有危机意识,当我们年级大了,有哪些亮点,与比我们经历更旺盛的年轻小工程师,竞争。

  • 无论你现在水平怎么样一定要 持续学习 没有鸡汤,别人看起来的毫不费力,其实费了很大力,这四个字就是我的建议!!!!!!!!!

  • 准备想说怎么样写简历,想象算了,我觉得,技术就是你最好的简历

  • 我希望每一个努力生活的it工程师,都会得到自己想要的,因为我们很辛苦,我们应得的。

  • 有什么问题想交流,欢迎给我私信,欢迎评论

【附】相关架构及资料

[外链图片转存中…(img-5VmDg3Ii-1711274445277)]

[外链图片转存中…(img-nWtRQu5v-1711274445277)]

内含往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值