kotlin kmp 副作用函数 effect

在 Kotlin Multiplatform (KMP) Compose 中,“effect functions”(或“effect handlers”)是专门的可组合函数,用于在 UI 中管理副作用。

在 Compose 中,可组合函数应该是“纯”的和声明式的。这意味着它们应该理想地只接受输入并生成 UI,而不引起其作用域之外的任何变化。然而,现实世界中的应用程序通常需要与“外部世界”进行交互,例如:

  • 网络请求:从 API 获取数据。
  • 数据库操作:保存或加载数据。
  • 日志/分析:将数据发送到外部服务。
  • 管理生命周期依赖的资源:注册/注销监听,器管理订阅。
  • 触发一次性 UI 事件:显示一个 Snackbar,导航到另一个屏幕。
  • 更新非 Compose 状态:与 ViewModel 或其他非 Compose 状态持有者交互。

这些操作被称为“副作用”,因为它们改变了应用程序在即时 UI 渲染过程之外的状态。如果处理不当,它们可能会导致不可预测的行为、错误或性能问题。

为什么需要 Effect Functions?

Compose 的重组模型意味着可组合函数可能会频繁且以任意顺序被调用。如果将副作用直接放入普通的可组合函数中,它们可能会被重复执行或在不适当的时间执行,从而导致问题。Effect functions 提供了一种受控且具有生命周期感知能力的方式来执行这些副作用。

KMP Compose 中最常见的 effect functions:

  1. LaunchedEffect
  • 用途:启动一个与可组合生命周期绑定的协程(异步操作),并依赖于一组“keys”。
  • 何时使用:当需要在可组合进入组合时执行挂起函数(例如,网络请求、数据库调用),或者当特定“key”(状态变量或参数)发生变化时。如果 key 发生变化,LaunchedEffect 启动的前一个协程将自动取消,并启动一个新的协程。
  • 示例代码:
    @Composablefun UserProfileScreen(userId: String) {var userData by remember { mutableStateOf<UserData?>(null) }LaunchedEffect(key1 = userId) {userData = fetchUserData(userId)}if (userData != null) {Text(text = "Name: ${userData?.name}")Text(text = "Email: ${userData?.email}")} else {CircularProgressIndicator()}}suspend fun fetchUserData(userId: String): UserData {// 模拟网络请求delay(1000)return UserData(name = "John Doe", email = "john.doe@example.com")}data class UserData(val name: String, val email: String)```2. DisposableEffect- 用途:执行与可组合生命周期和 keys 相关联的设置和清理操作。
- 何时使用:当需要管理需要显式清理的资源时。它提供了一个 onDispose 块,当可组合离开组合或者其 keys 发生变化时(意味着 effect 被“处置”,可能会设置一个新的 effect)执行。
- 示例代码:

@Composable
fun LocationScreen() {
var location by remember { mutableStateOf<String?>(null) }

    DisposableEffect(Unit) {val listener = object : LocationListener {override fun onLocationChanged(loc: Location) {location = "${loc.latitude}, ${loc.longitude}"}}// 注册监听器registerLocationListener(listener)onDispose {// 注销监听器unregisterLocationListener(listener)}}if (location != null) {Text(text = "Current Location: $location")} else {Text(text = "No location available")}
}
  1. SideEffect
  • 用途:在可组合函数成功重组时运行非挂起代码。

  • 何时使用:在成功重组后,将 Compose 状态与外部、非 Compose 管理的对象同步。它确保代码在 UI 更新后运行。

  • 示例代码:

    @Composable
    fun LoggingScreen() {
    var counter by remember { mutableStateOf(0) }

      SideEffect {log("Counter value is now $counter")}Button(onClick = { counter++ }) {Text(text = "Increment")}
    

    }

    fun log(message: String) {
    println(“LOG: $message”)
    }```

  1. rememberCoroutineScope
  • 用途:获取一个与可组合生命周期绑定的 CoroutineScope。

  • 何时使用:当需要从 Compose 作用域之外的回调(例如,Button 的 onClick lambda)中启动协程,但仍然希望当可组合离开组合时取消协程。可以在回调中手动调用 .launch { … }。

  • 示例代码:

    @Composable
    fun DelayedActionScreen() {
    var message by remember { mutableStateOf<String?>(null) }
    val scope = rememberCoroutineScope()

      Button(onClick = {scope.launch {delay(2000)message = "Action completed after 2 seconds"}}) {Text(text = "Perform Delayed Action")}if (message != null) {Text(text = message!!)}
    

    }

  1. produceState
  • 用途:将非 Compose 可观察状态(例如,基于回调的 API,Android 中的 Flow 或 LiveData)转换为 Compose State,以便其他可组合函数可以观察它。
  • 何时使用:当需要将现有的命令式 API 或数据流集成到 Compose UI 中时。它启动一个协程来随时间更新 State。
  • 示例代码:
 @Composablefun DataScreen() {val data = produceState(initialValue = "Loading...") {val flow = fetchDataFlow()collect {value = it}}Text(text = data.value)}fun fetchDataFlow(): Flow<String> {return flow {delay(1000)emit("Data loaded")}}```6. derivedStateOf- 用途:从其他 State 对象创建一个 State,但只有当派生值实际发生变化时才会重组,而不是只要底层状态发生变化就重组。
- 何时使用:当基于其他状态有复杂的计算或转换,并且只想在派生值的结果发生变化时才触发重组时,用于性能优化。
- 示例代码:
@Composable
fun DerivedStateScreen() {var x by remember { mutableStateOf(0) }var y by remember { mutableStateOf(0) }val derivedState = derivedStateOf {x + y}Text(text = "Derived State: ${derivedState.value}")Button(onClick = { x++ }) {Text(text = "Increment x")}Button(onClick = { y++ }) {Text(text = "Increment y")}
}

7. snapshotFlow- 用途:将 Compose State 对象转换为 Kotlin Flow。
- 何时使用:当想利用 Kotlin Flows 的强大功能(例如,map、filter、debounce 等操作符)与 Compose State 时。
- 示例代码:

@Composable
fun DebouncedSearchScreen() {
var query by remember { mutableStateOf(“”) }

    val flow = snapshotFlow { query }.debounce(300).collect { performSearch(it)}TextField(value = query, onValueChange = { query = it })
}fun performSearch(query: String) {println("Performing search for: $query")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…

【Pandas】pandas DataFrame isna

Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值&#xff08;NaN&#xff09;DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充&#xff08;即“下一个有效观测值”&#xff09…

MQTT协议:物联网时代的通信基石

MQTT协议&#xff1a;物联网时代的通信基石 在当今快速发展的物联网&#xff08;IoT&#xff09;时代&#xff0c;设备之间的通信变得尤为重要。MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;协议作为一种轻量级的消息传输协议&#xff0c;正逐渐成为物联…

Excel 表格内批量添加前缀与后缀的实用方法

我们经常需要为 Excel 表格中的内容统一添加前缀或后缀&#xff0c;例如给编号加“NO.”、给姓名加“会员_”等。手动操作效率低&#xff0c;本文将介绍几种实用的方法&#xff0c;帮助你快速完成批量添加前缀和后缀的操作。 使用“&”运算符添加前缀或后缀&#xff08;推…

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…

分布式锁实战:Redisson vs. Redis 原生指令的性能对比

分布式锁实战&#xff1a;Redisson vs. Redis 原生指令的性能对比 引言 在DIY主题模板系统中&#xff0c;用户可自定义聊天室的背景、图标、动画等元素。当多个运营人员或用户同时修改同一模板时&#xff0c;若没有锁机制&#xff0c;可能出现“甲修改了背景色&#xff0c;乙…

C++ 设计模式《复制粘贴的奇迹:小明的原型工厂》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;原型模式&#xff08;Prototype Pattern&#xff09; &#x1f4d6; 背景故事 创业初期&#xff0c;小明每天加班写配送路线、配送策略、营销套餐。可当业务做大后&#xff0c;他发现大家常常下单“上次那个套餐”—— “老…

【Elasticsearch】映射:fielddata 详解

映射&#xff1a;fielddata 详解 1.fielddata 是什么2.fielddata 的工作原理3.主要用法3.1 启用 fielddata&#xff08;通常在 text 字段上&#xff09;3.2 监控 fielddata 使用情况3.3 清除 fielddata 缓存 4.使用场景示例示例 1&#xff1a;对 text 字段进行聚合示例 2&#…

开源 vGPU 方案:HAMi,实现细粒度 GPU 切分

本文主要分享一个开源的 GPU 虚拟化方案&#xff1a;HAMi&#xff0c;包括如何安装、配置以及使用。 相比于上一篇分享的 TimeSlicing 方案&#xff0c;HAMi 除了 GPU 共享之外还可以实现 GPU core、memory 得限制&#xff0c;保证共享同一 GPU 的各个 Pod 都能拿到足够的资源。…

PlayDiffusion上线:AI语音编辑进入“无痕时代”

在语音合成与语音编辑领域&#xff0c;一个长期存在的挑战是如何在修改语音内容的同时&#xff0c;保持原始语音的自然性、连贯性和说话人特征。近日&#xff0c;一款名为 PlayDiffusion 的新型 AI 语音修复模型应运而生&#xff0c;成功实现了这一目标。 PlayDiffusion 是一个…

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…

微信小程序前端面经

一、技术栈与编码能力&#xff08;10min&#xff09; 1. Vue 3 & Composition API Q1&#xff1a;请解释一下 ref 和 reactive 的区别&#xff1f;你在项目中是如何使用的&#xff1f; 答&#xff1a;ref是包装一个原始值或对象&#xff0c;通过.value访问&#xff0c;r…

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…

Houdini POP入门学习07 - 分组

使用PopGroup可对粒子进行分组操作&#xff0c;并通过表达式从而更灵活的处理粒子行为。 1.创建box作为发射器&#xff0c;连接popnet节点。 2.双击进入popnet&#xff0c;添加popwind添加向上风力。现在播放粒子可见粒子向上方移动。 3.添加popgroup进行分组&#xff0c;开启…

机器学习复习3--模型评估

误差与过拟合 我们将学习器对样本的实际预测结果与样本的真实值之间的差异称为&#xff1a;误差&#xff08;error&#xff09;。 误差定义&#xff1a; ①在训练集上的误差称为训练误差&#xff08;training error&#xff09;或经验误差&#xff08;empirical error&#x…

Docker 镜像上传到 AWS ECR:从构建到推送的全流程

一、在 EC2 实例中安装 Docker&#xff08;适用于 Amazon Linux 2&#xff09; 步骤 1&#xff1a;连接到 EC2 实例 ssh -i your-key.pem ec2-useryour-ec2-public-ip步骤 2&#xff1a;安装 Docker sudo yum update -y sudo amazon-linux-extras enable docker sudo yum in…

MobileNet 改进:基于MobileNetV2和SSPP的图像分类

1.创新点分析 在计算机视觉领域,高效的图像分类模型一直是研究热点。 本文将详细解析一个结合了MobileNetV2和空间金字塔池化(SSPP)的深度学习模型实现。 模型概述 这个代码实现了一个轻量级但功能强大的图像分类器,主要包含两个核心组件: MobileNetV2作为特征提取器 自定…