前言
用kotlin 搬砖Android 就知道,在Android 中viewModel 中使用协程,建议用viewModelScope。这个玩意需要导入包:
androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2
嗯,在google Android 中 有这么一句话:
ViewModelScope
是为 ViewModel您的应用程序中的每个定义的。如果清除,在此范围内启动的任何协程都会自动取消ViewModel
。当您只有在活动时才需要完成工作时,协程非常有用ViewModel
。例如,如果您正在计算布局的一些数据,则应将工作范围限制在 ,ViewModel
以便在ViewModel
清除 时,工作会自动取消以避免消耗资源。
通俗的理解就是,viewModelScope创建的协程的生命周期和viewModel 的生命周期是绑定的,当viewModel 被取消的时候,viewModelScope创建的协程也会被取消。而我们知道,VIewMoel 的生命周期和Activity或fragment 绑定的。
viewModel 如何取消后台任务
在activity的源码 androidx.activity.ComponentActivity 代码中:
可以看到,当activity 处于ON_DESTROY的时候,会调用 :
通常来说,界面的配置是不会更改的,更改的时候,比如说,横竖屏切换,比如说 字体,字号,系统主题等等。所以我们就可以简单认为当activity 销毁的时候,就会销毁这个玩意。我们知道 ViewModelStore是用于存放多个viewModel 的,所以他的clear,其实也通过循环调用的VIewModel 中的clear() 函数。
而fragment 中就稍显复杂,我们这里先不讨论这个玩意。
结合activity 里面调用ViewModel 的clear() 函数的思路,我们就可以发现,无论是JAVA 还是kotlin 需要终止一个后台任务,其中一个办法就是重写ViewModel 中和clear() 相关的函数。但是我们通过阅读源码可以发现:
这个函数不可更改,但是他在clear() 函数中调用了:
那么我们想要取消自己的后台任务,那么其中一个思路就是重写onCleared 函数,那么还有没有其他思路呢?我们结合clear的源码:
可以看到,两个变量mBagOfTags和mCloseables 都调用了closeWithRuntimeException 函数。
当循环对象是实现与Closeable 的时候,就调用Closeable 的close() 函数。所以我们还有一个思路,就是后台任务实现Closeable 接口,然后为viewModel 添加mBagOfTags或mCloseables。具体添加什么,看业务诉求,结合源码:
我们可以看出mBagOfTags 适合用于要取值得情况,而mCloseables 则通常用于不需要取出来的情况。OK,到这里,我们可以大概知道viewModel 中取消后台任务的几种方式了,那么viewModelScope 想要取消,就一定得通过这几种方式来处理。
viewModelScope 如何取消后台任务
在没有看viewModelScope 的源码 时候,我们可以猜测一下 viewModelScope是如何实现的,这个玩意是变量,而且是一个额外的库实现的,所以,这个这个玩意的实现,一定是扩展属性,对吧。但是扩展属性,得有一个地方存放这个调调,总不能存储为全局变量吧,而恰好,viewModel 中有一个mBagOfTags 支持存取,所以他可能是用到了mBagOfTags。OK,那么我们就来看源码:
源码超级少,超级单纯好吧。viewModelScope是一个实现Closeable接口的CoroutineScope,而CoroutineScope是协程上下文。我们创建协程的时候,这个玩意是必要的。所以:
这个的作用其实是取消协程。
重写了viewModelScope的get方法,优先在viewModel 中的mBagOfTags获取,如果没有就创建一个新的,这么就保证了viewModelScope在viewModel 中的唯一性,我们通过viewModelScope 创建的所有协程,都将是viewModelScope的子协程,我们知道当父协程取消的时候,子协程也将被取消,所以viewModelScope其实是利用了这个特性。viewModelScope被添加到mBagOfTags,当viewModel 被取消的时候,会取消mBagOfTags 里面的Closeable。
总结
其实这个代码逻辑是非常简单的,利用了Closeable接口和扩展属性,利用viewModel 取消mBagOfTags的特性实现了这一功能。
最后
如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。
如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。