10分钟带你搞懂协程、LiveData-和-Flow,最新大厂Android社招面试经验汇总

lifecycleScope.launch {
// Run
}

}
}

有些时候,您可能还需要在生命周期的某个状态 (启动时/恢复时等) 执行一些操作,这时您可以使用 launchWhenStarted、launchWhenResumed、launchWhenCreated 这些方法:

class MyActivity : Activity {
override fun onCreate(state: Bundle?) {
super.onCreate(savedInstanceState)

lifecycleScope.launch {
// Run
}

lifecycleScope.launchWhenResumed {
// Run
}
}
}

注意,如果您在 launchWhenStarted 中设置了一个操作,当 Activity 被停止时,这个操作也会被暂停,直到 Activity 被恢复 (Resume)。

最后一种作用域的情况是贯穿整个应用。如果这个操作非常重要,您需要确保它一定被执行,这时请考虑使用 WorkManager。比如您编写了一个发推的应用,希望撰写的推文被发送到服务器上,那这个操作就需要使用 WorkManager 来确保执行。而如果您的操作只是清理一下本地存储,那可以考虑使用 Application Scope,因为这个操作的重要性不是很高,完全可以等到下次应用启动时再做。

接下来我们看看如何在 viewModelScope 里使用 LiveData。以前我们想在协程里做一些操作,并将结果反馈到 ViewModel 需要这么操作:

class MyViewModel : ViewModel {
private val _result = MutableLiveData()
val result: LiveData = _result

init {
viewModelScope.launch {
val computationResult = doComputation()
_result.value = computationResult
}
}
}

看看我们做了什么:

  1. 准备一个 ViewModel 私有的 MutableLiveData (MLD)
  2. 暴露一个不可变的 LiveData
  3. 启动协程,然后将其操作结果赋给 MLD

这个做法并不理想。在 LifeCycle 2.2.0 之后,同样的操作可以用更精简的方法来完成,也就是 LiveData 协程构造方法 (coroutine builder):

class MyViewModel {
val result = liveData {
emit(doComputation())
}
}

这个 liveData 协程构造方法提供了一个协程代码块,这个块就是 LiveData 的作用域,当 LiveData 被观察的时候,里面的操作就会被执行,当 LiveData 不再被使用时,里面的操作就会取消。而且该协程构造方法产生的是一个不可变的 LiveData,可以直接暴露给对应的视图使用。而 emit() 方法则用来更新 LiveData 的数据。

让我们来看另一个常见用例,比如当用户在 UI 中选中一些元素,然后将这些选中的内容显示出来。一个常见的做法是,把被选中的项目的 ID 保存在一个 MutableLiveData 里,然后运行 switchMap。现在在 switchMap 里,您也可以使用协程构造方法:

private val itemId = MutableLiveData()
val result = itemId.switchMap {
liveData { emit(fetchItem(it)) }
}

LiveData 协程构造方法还可以接收一个 Dispatcher 作为参数,这样您就可以将这个协程移至另一个线程。

liveData(Dispatchers.IO) {
}

最后,您还可以使用 emitSource() 方法从另一个 LiveData 获取更新的结果:

liveData(Dispatchers.IO) {
emit(LOADING_STRING)
emitSource(dataSource.fetchWeather())
}

接下来我们来看如何取消协程。绝大部分情况下,协程的取消操作是自动的,毕竟我们在对应的作用域里启动一个协程时,也同时明确了它会在何时被取消。但我们有必要讲一讲如何在协程内部来手动取消协程。

这里补充一个大前提: 所有 kotlin.coroutines 的 suspend 方法都是可取消的。比如这种:

suspend fun printPrimes() {
while(true) {
// Compute
delay(1000)
}
}

在上面这个无限循环里,每一个 delay 都会检查协程是否处于有效状态,一旦发现协程被取消,循环的操作也会被取消。

那问题来了,如果您在 suspend 方法里调用的是一个不可取消的方法呢?这时您需要使用 isActivate 来进行检查并手动决定是否继续执行操作:

suspend fun printPrimes() {
while(isActive) {
// Compute
}
}

LiveData 操作实践

在进入具体的操作实践环节之前,我们需要区分一下两种操作: 单次 (One-Shot) 操作和监听 (observers) 操作。比如 Twitter 的应用:

单次操作,比如获取用户头像和推文,只需要执行一次即可。 监听操作,比如界面下方的转发数和点赞数,就会持续更新数据。

让我们先看看单次操作时的内容架构:

如前所述,我们使用 LiveData 连接 View 和 ViewModel,而在 ViewModel 这里我们则使用刚刚提到的 liveData 协程构造方法来打通 LiveData 和协程,再往右就是调用 suspend 方法了。

如果我们想监听多个值的话,该如何操作呢?

第一种选择是在 ViewModel 之外也使用 LiveData:

△ Reopsitory 监听 Data Source 暴露出来的 LiveData,同时自己也暴露出 LiveData 供 ViewModel 使用

但是这种实现方式无法体现并发性,比如每次用户登出时,就需要手动取消所有的订阅。LiveData 本身的设计并不适合这种情况,这时我们就需要使用第二种选择: 使用 Flow。

ViewModel 模式

当 ViewModel 监听 LiveData,而且没有对数据进行任何转换操作时,可以直接将 dataSource 中的 LiveData 赋值给 ViewModel 暴露出来的 LiveData:

val currentWeather: LiveData =
dataSource.fetchWeather()

如果使用 Flow 的话就需要用到 liveData 协程构造方法。我们从 Flow 中使用 collect 方法获取每一个结果,然后 emit 出来给 liveData 协程构造方法使用:

val currentWeatherFlow: LiveData = liveData {
dataSource.fetchWeatherFlow().collect {
emit(it)
}
}

不过 Flow 给我们准备了更简单的写法:

val currentWeatherFlow: LiveData =
dataSource.fetchWeatherFlow().asLiveData()

接下来一个场景是,我们先发送一个一次性的结果,然后再持续发送多个数值:

val currentWeather: LiveData = liveData {
emit(LOADING_STRING)
emitSource(dataSource.fetchWeather())
}

在 Flow 中我们可以沿用上面的思路,使用 emit 和 emitSource:

val currentWeatherFlow: LiveData = liveData {
emit(LOADING_STRING)
emitSource(
dataSource.fetchWeatherFlow().asLiveData()
)
}

但同样的,这种情况 Flow 也有更直观的写法:

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

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

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

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
img

面试复习笔记:

这份资料我从春招开始,就会将各博客、论坛。网站上等优质的Android开发中高级面试题收集起来,然后全网寻找最优的解答方案。每一道面试题都是百分百的大厂面经真题+最优解答。包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
给文章留个小赞,就可以免费领取啦~

戳我领取:GitHub

《960页Android开发笔记》

《1307页Android开发面试宝典》

包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

[外链图片转存中…(img-bJAlTqet-1711269234224)]

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的ViewMode是一种用于管理UI组件状态的架构组件。它允许将数据的变化动态地反映在UI上,并遵循单一职责原则,将界面逻辑和业务逻辑分离开来。 ViewMode提供了一种以响应式编程风格来处理UI更新的方式。它可以观察数据的变化,并在数据变化时通知相应的UI组件进行更新。通过将数据分离到ViewMode中,我们可以确保在设备旋转等界面重新创建时不会丢失数据。 LiveData是一种具体的观察者模式实现,它用于在ViewMode和UI组件之间传输数据。LiveData是生命周期感知的,这意味着它会自动感知组件的生命周期状态,并在必要时更新数据。例如,当一个Activity处于非活动状态时,LiveData会暂停发布结果,避免不必要的UI更新。 LiveData的另一个重要特性是数据更新是异步的。这意味着数据的更新操作不会阻塞主线程,避免了数据操作对UI性能的影响。 通过将ViewMode和LiveData结合使用,我们可以实现数据的实时更新和UI的同步更新。ViewMode负责管理数据和业务逻辑,而LiveData负责将数据的变化通知给UI组件,以便它们可以及时更新。这种架构可以提高代码的可维护性和测试性,同时也能提供更好的用户体验。 总结起来,Android中的ViewMode和LiveData是一种用于管理UI组件状态和实现数据更新的架构组件。它们可以帮助我们以响应式编程的方式处理UI更新,提供更好的用户体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值