当前位置: 首页 > news >正文

源码解读笔记:协程的 ViewModel.viewModelScope和LifecycleOwner.lifecycleScope

分析下ViewModel.viewModelScope

public val ViewModel.viewModelScope: CoroutineScopeget() {val scope: CoroutineScope? = this.getTag(JOB_KEY)if (scope != null) {return scope}return setTagIfAbsent(JOB_KEY,CloseableCoroutineScope(SupervisorJob() + Dispatchers.Main.immediate))}internal class CloseableCoroutineScope(context: CoroutineContext) : Closeable, CoroutineScope {override val coroutineContext: CoroutineContext = contextoverride fun close() {coroutineContext.cancel()}
}

1. ViewModel.viewModelScope:

这是一个公共的只读属性,用于获取或创建与 ViewModel 关联的 CoroutineScope。
get 函数用于计算属性值。它首先尝试从 ViewModel 的 tag(存储在 this.getTag(JOB_KEY) 中)获取已存在的 CoroutineScope。
如果找到了已存在的 CoroutineScope(scope != null),则直接返回它。
如果没有找到,它将创建一个新的 CloseableCoroutineScope 并将其设置为 ViewModel 的 tag,同时返回新创建的 CoroutineScope。
创建的 CoroutineScope 由一个 SupervisorJob 和 Dispatchers.Main.immediate 组成,这表示协程将在主线程上运行,并且具有超时监督策略。

2. CloseableCoroutineScope:

这是一个内部类,实现了 Closeable 和 CoroutineScope 接口。
实现了 CoroutineScope.coroutineContext 属性,它返回给定的 CoroutineContext 参数,通常是一个组合了 Job 和 Dispatcher 的上下文。
实现了 Closeable.close() 方法,当调用 close() 时,它会取消关联的 CoroutineContext,这通常意味着取消所有正在运行的协程。
总结一下,这段代码的主要目的是为 ViewModel 提供一个可管理的协程作用域,这个作用域与 ViewModel 的生命周期绑定,并且可以在需要时安全地取消所有协程。
CloseableCoroutineScope 确保了协程的生命周期管理,当不再需要时可以被关闭,从而避免资源泄漏。Dispatchers.Main.immediate 确保所有在此作用域内启动的协程都在主线程上执行,这对于更新 UI 是必要的。

3. 其中的SupervisorJob()

SupervisorJob 是 Kotlin 协程库中的一个类,它是 Job 的一个子类,主要用于管理协程的生命周期。
SupervisorJob 的主要特点是它采用了所谓的“非传播”异常策略,这意味着如果在其子协程中发生异常,SupervisorJob 不会因为这些异常而自动取消自身或其他子协程。
这种设计是为了防止一个子任务的错误导致整个工作树的崩溃,使得其他任务有机会完成或者独立处理错误。
使用 SupervisorJob 的场景通常包括:

  • 错误隔离:如果你希望一个子任务的失败不会影响其他子任务,可以使用 SupervisorJob 创建这些子任务的父级作用域。
  • 独立性:在多个任务之间需要保持独立性,即使其中一个失败,其他任务也应该继续运行。
  • 资源清理:在某些情况下,你可能希望即使有子任务失败,仍然能够执行清理操作,如关闭文件流或网络连接。
    在上述代码中,SupervisorJob() 被用来创建一个 CloseableCoroutineScope 的上下文,这意味着在这个作用域内启动的所有协程都将受到 SupervisorJob 的管理,它们会在主线程上运行,并且即使其中一个协程由于异常而终止,其他协程仍将继续执行。
    这对于 ViewModel 来说是一个很好的选择,因为它允许 ViewModel 中的不同任务独立处理错误,而不是整体崩溃。


分析下LifecycleOwner.lifecycleScope:

public val LifecycleOwner.lifecycleScope: LifecycleCoroutineScopeget() = lifecycle.coroutineScope

定义了一个扩展属性 coroutineScope,适用于 Lifecycle 类型的对象。这个属性返回一个 LifecycleCoroutineScope 对象。

public val Lifecycle.coroutineScope: LifecycleCoroutineScopeget() {while (true) {val existing = mInternalScopeRef.get() as LifecycleCoroutineScopeImpl?if (existing != null) {return existing}val newScope = LifecycleCoroutineScopeImpl(this,SupervisorJob() + Dispatchers.Main.immediate)if (mInternalScopeRef.compareAndSet(null, newScope)) {newScope.register()return newScope}}}
  • 使用无限循环来确保在多线程环境下正确获取或创建 LifecycleCoroutineScope。
  • 检查现有作用域:从 mInternalScopeRef 中获取现有的 LifecycleCoroutineScopeImpl 实例。 如果存在现有实例,则直接返回该实例。
  • 否则,创建新作用域:创建一个新的 LifecycleCoroutineScopeImpl 实例。
    • this 表示当前的 Lifecycle 对象。
    • SupervisorJob() 创建一个监督者作业,允许子作业独立于父作业失败。
    • Dispatchers.Main.immediate 确保协程在主线程上立即执行
  • 原子性设置:使用 compareAndSet 方法尝试原子地将 mInternalScopeRef 设置为新的 newScope。
    • 如果设置成功,则调用 newScope.register() 注册新作用域,并返回新作用域。
    • 如果设置失败(即已经有其他线程设置了 mInternalScopeRef),则继续循环,重新检查现有作用域。

总结

  • 目的:这个属性 coroutineScope 提供了一个与 Lifecycle 绑定的协程作用域,确保在生命周期管理下安全地执行协程。
  • 线程安全:通过无限循环和 compareAndSet 方法,确保在多线程环境下正确创建和获取 LifecycleCoroutineScope。
  • 作用域配置:使用 SupervisorJob 和 Dispatchers.Main.immediate 配置协程作用域,确保协程在主线程上立即执行,并且子协程可以独立于父协程失败。
    使用场景
  • 生命周期绑定:在 Fragment 或 Activity 中使用 lifecycleScope 可以确保协程在组件的生命周期内安全地执行,避免内存泄漏和资源浪费。
  • 主线程操作:适用于需要在主线程上执行的 UI 相关操作,如更新界面、处理用户交互等

相关文章:

源码解读笔记:协程的 ViewModel.viewModelScope和LifecycleOwner.lifecycleScope

分析下ViewModel.viewModelScope public val ViewModel.viewModelScope: CoroutineScopeget() {val scope: CoroutineScope? this.getTag(JOB_KEY)if (scope ! null) {return scope}return setTagIfAbsent(JOB_KEY,CloseableCoroutineScope(SupervisorJob() Dispatchers.Ma…...

11.27周三F34-Day8打卡

文章目录 1. 学习让我感觉很棒。(什么关系?动作 or 描述?主语部分是?)解析答案:【解析答案分析】【对比分析】【拓展内容】2. 她忽然想起来钥匙放另一个包里了。解析答案:【拓展内容】3. 她来不来都没关系。(该由什么引导?这句话又属于什么关系,动作 or 描述?)解析答案…...

XG(S)-PON原理

前言 近年来,随着全球范围内接入市场的飞快发展以及全业务运营的快速开展,已有的PON技术标准在带宽需求、业务支撑能力以及接入节点设备和配套设备的性能提升等方面都面临新的升级需求XG(S)-PON(10G GPON)是在已有GPON技术标准上演进的增强下一代GPON技…...

C语言实例之9斐波那契数列实现

1. 斐波那契数列简介 斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多・斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为 “兔子数列”。 它的特点是从第三…...

YOLO系列论文综述(从YOLOv1到YOLOv11)【第1篇:概述物体检测算法发展史、YOLO应用领域、评价指标和NMS】

目录 1 前言2 YOLO在不同领域的应用3 物体检测指标和NMS3.1 mAP和IOU3.2 mAP计算流程3.2.1 VOC 数据集3.2.2 微软 COCO 数据集 3.3 NMS 1 前言 最近在做目标检测模型相关的优化,重新看了一些新的论文,发现了几篇写得比较好的YOLO系列论文综述&#xff0…...

数据结构--Map和Set

目录 一.二叉搜索树1.1 概念1.2 二叉搜索树的简单实现 二.Map2.1 概念2.2 Map常用方法2.3 Map使用注意点2.4 TreeMap和HashMap的区别2.5 HashMap底层知识点 三.Set3.1 概念3.2 Set常用方法3.3 Set使用注意点3.4 TreeSet与HashSet的区别 四.哈希表4.1 概念4.2 哈希冲突与避免4.3…...

计算机操作系统——进程控制(Linux)

进程控制 进程创建fork()函数fork() 的基本功能fork() 的基本语法fork() 的工作原理fork() 的典型使用示例fork() 的常见问题fork() 和 exec() 结合使用总结 进程终止与$进程终止的本质进程终止的情况正常退出(Exit)由于信号终止非…...

【前端】ES6基础

1.开发工具 vscode地址 :https://code.visualstudio.com/download, 下载对应系统的版本windows一般都是64位的 安装可以自选目录,也可以使用默认目录 插件: 输入 Chinese,中文插件 安装: open in browser,直接右键文件…...

【排序算法 python实现】

排序算法 python实现 / 默写 # 汉诺塔 import copy import randomdef hanuo(n, a, b, c):if n 1:print(f{a} --> {c})returnhanuo(n - 1, a, c, b)print(f{a} --> {c})hanuo(n - 1, b, a, c)hanuo(3, A, B, C)# 冒泡排序 def bubble_sort(arr):n len(arr)for i in ran…...

Java图书管理系统(简易保姆级)

前面学习了这么多知识,为了巩固之前的知识,我们就要写一个图书管理系统来帮助大家复习,让大家的知识融会贯通~~~ 话不多说,直接开始今天的内容~ 首先呢,我们要有一个大体的思路: 实现效果思路有两种情况&a…...

嵌入式硬件设计:从概念到实现的全流程

嵌入式硬件设计是现代电子技术中一个至关重要的领域,涉及从硬件架构设计到硬件调试的各个方面。它为我们日常生活中的各类智能设备、家电、工业控制系统等提供了强大的支持。本文将介绍嵌入式硬件设计的基本流程、关键技术、常用工具以及常见的挑战和解决方案&#…...

第 4 章 Java 并发包中原子操作类原理剖析

原子变量操作类 AtomicLong 是原子性递增或者递减类,其内部使用 Unsafe 来实现,AtomicLong类也是在 rt.jar 包下面的,AtomicLong 类就是通过 BootStarp 类加载器进行加载的。这里的原子操作类都使用 CAS 非阻塞算法 private static final lon…...

从 0 到 1 掌握部署第一个 Web 应用到 Kubernetes 中

文章目录 前言构建一个 hello world web 应用项目结构项目核心文件启动项目 检查项目是否构建成功 容器化我们的应用编写 Dockerfile构建 docker 镜像推送 docker 镜像仓库 使用 labs.play-with-k8s.com 构建 Kubernetes 集群并部署应用构建 Kubernetes 集群环境编写部署文件 总…...

政安晨【零基础玩转各类开源AI项目】探索Cursor-AI Coder的应用实例

目录 Cusor的主要特点 Cusor实操 政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! Cursor 是 Visual Studio Code 的一个分支。这使我们能够…...

CentOS 7 安装部署 KVM

1.关闭虚拟机 打开相关选项 打开虚拟机centos7 连接xshell 测试网络,现在就是没问题的,因为我们要使用网络源 安装 GNOME 桌面环境 安装KVM 模块 安装KVM 调试工具 构建虚拟机的命令行工具 qemu 组件,创建磁盘、启动虚拟机等 输入这条命令,…...

ArcGIS 10.2软件安装包下载及安装教程!

今日资源:ArcGIS 适用系统:WINDOWS 软件介绍:ArcGIS是一款专业的电子地图信息编辑和开发软件,提供一种快速并且使用简单的方式浏览地理信息,无论是2D还是3D的信息。软件内置多种编辑工具,可以轻松的完成地…...

一个专为云原生环境设计的高性能分布式文件系统

大家好,今天给大家分享一款开源创新的分布式 POSIX 文件系统JuiceFS,旨在解决海量云存储与各类应用平台(如大数据、机器学习、人工智能等)之间高效对接的问题。 项目介绍 JuiceFS 是一款面向云原生设计的高性能分布式文件系统&am…...

基于深度学习CNN算法的花卉分类识别系统01--带数据集-pyqt5UI界面-全套源码

文章目录 基于深度学习算法的花卉分类识别系统一、项目摘要二、项目运行效果三、项目文件介绍四、项目环境配置1、项目环境库2、环境配置视频教程 五、项目系统架构六、项目构建流程1、数据集2、算法网络Mobilenet3、网络模型训练4、训练好的模型预测5、UI界面设计-pyqt56、项目…...

3174、清除数字

3174、[简单] 清除数字 1、题目描述 给你一个字符串 s 。你的任务是重复以下操作删除 所有 数字字符: 删除 第一个数字字符 以及它左边 最近 的 非数字 字符。 请你返回删除所有数字字符以后剩下的字符串。 2、解题思路 遍历字符串: 我们需要逐个遍…...

C++ 优先算法 —— 无重复字符的最长子串(滑动窗口)

目录 题目: 无重复字符的最长子串 1. 题目解析 2. 算法原理 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口(同向双指针) 3. 代码实现 Ⅰ. 暴力枚举 Ⅱ. 滑动窗口 题目: 无重复字符的最长子串 1. 题目解析 题目截图: 此题所说的…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: ​onCreate()​​ ​调用时机​:Activity 首次创建时调用。​…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】:开启编程世界的奇妙冒险 嘿,各位编程小白探险家!欢迎来到 C# 的奇幻大陆!今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类!别害怕,跟着我,保准让你轻松搞…...