Compose中的一些机制验证与总结——remember

Compose 中状重组 在某些场景下,状态可能会连续变化,可能会导致中间态的重组在执行时被打断,新的重组会插进来,对于被打断的重组,Compose 不会将执行一半的结果反应到视图树上,因为最后一次的状态总归是正确的。结果符合我们的预期。最后总结一下:本文接着上篇文章的状态,讲解了重组的一些特性,如何确定重组的范围,以及重组的中的类型稳定性概念,以及如何提升非稳定类型在重组过程中的性能。需要注意的是,重组的范围,与只能跳过并不冲突,确定了重组范围,会调用对应的组件代码,但是当参数没有变化时,在运行时不会真正执行,会跳过本次重组。 阅读详情

最近在搞一个基于 Compose 实现的低代码跨平台项目,涉及到一些 Compose 运行时的一些机制问题,周末写了个 demo 验证总结一下,总体是与过往经验相符的,也发现了一些小的细节是以前不太清楚的,可以一起学习研究一下,如有错误欢迎指正!

remember 简介

先贴一段 GPT4 给的简介:

remember 是 Jetpack Compose 中的一个核心函数,它用于记住那些你不希望在重组(recomposition)时重新创建的数据。举个例子,这可能是一种状态、一个对象实例或一个计算成本较高的结果。它有助于保持性能并避免不必要的计算。

使用示例

先看测试代码:

@Composable
fun ContentView(index: Int) {
    val item = remember {
        mutableStateOf(DataA()).also {
            Log.d("Test", "ContentView in remember, item=$it")
        }
    }
    
    Column(
        modifier = Modifier
            .fillMaxSize()
            .border(3.dp, Color.Cyan)
    ) {
        Text(text = "this is page $index,\n item= $item")
    }
}


class DataA(
    val id: Int = 0,
    val name: String = ""
)

上面的代码中,我们定义了一个 ContentView 内容页,外面传进来一个 index,在 ContentView 组件内,我们用 remember 来包一个state变量,remember 里面打印一行日志方便观察 remember 内部的执行情况,页面就只显示"this is page $index,\n item= $item",打印出当前页面的 index 和 remember 的 item 对象,非常简单

接下来看我们怎么使用它:

常规使用

@Composable
fun TestCompose2() {
    var index by remember {
        mutableIntStateOf(0)
    }
    Column {
        Row {
            repeat(3) { repeatIndex ->
                TabBtn(repeatIndex) { tabIndex ->
                    index = tabIndex
                    Log.v("Test", "onClicked: tab_$tabIndex")
                }
            }
        }
        ContentView(index = index)
    }
}

@Composable
fun TabBtn(index: Int, onClicked: (Int) -> Unit) {
    OutlinedButton(onClick = { onClicked(index) }) {
        Text(text = "Tab $index")
    }
}

写过 compose 的同学应该脑海中已经有画面了对吧,没错,跑起来是这样的:
在这里插入图片描述

查看日志,remember 里面的日志也打印了
在这里插入图片描述

然后点击上面的 tab1,使页面切换:
在这里插入图片描述
在这里插入图片描述

我们发现页面切换之后,page 更新为 0 了,但是 item 对象还是没有变,而且remember 里面的那行日志也不会再次打印。

因为其实我们这样并不是真正的切换了 ContentView,ContentView 还是那个 ContentView,只是我们给他传的参数变了,使它发生重组(界面刷新)而已,而 remember 的作用正是处理这种重组的情况的

对比不使用remember的情况

而如果我们不使用 remeber ,将 ContentView 里的 item 那段改为如下:

	val item = run {
        mutableStateOf(DataA()).also {
            Log.d("Test", "ContentView in run, item=$it")
        }
    }

那么每次点击 tab 切换的时候,ContentView 发生重组,都会执行一遍这里的逻辑
在这里插入图片描述
所以这里每次都不一样了,即使切回到 tab0 之后,也不再是之前那个 item,所以这就是使用和不使用 remember 的区别

remember 无法处理的情况

如果我们稍微改一下用 ContentView 的方式,如下末尾 3 行代码:

@Composable
fun TestCompose2() {
    var index by remember {
        mutableIntStateOf(0)
    }
    Column {
        Row {
            repeat(3) { repeatIndex ->
                TabBtn(repeatIndex) { tabIndex ->
                    index = tabIndex
                    Log.v("Test", "onClicked: tab_$tabIndex")
                }
            }
        }
        when (index) {
            0 -> ContentView(index = 0)
            1 -> ContentView(index = 1)
            else -> ContentView(index = 2)
        }
    }
}

此时即使 ContentView 里用的时 remember,每次打印出的 item 对象也已经是新的对象了。如下:
在这里插入图片描述
这是因为此时切换 tab 之后实现了真正的切换不同的 ContentView,旧的 ContentView 被移出了可组合范围,下一次再回来的时候就会重新执行一遍 remember 内的逻辑。换句话说,remember 只能在函数存在于组合树且未被移除时保持其状态。

总结:

  1. remember 用于保存数据,这些数据只应该在 Compose 函数的重组过程中保持不变,但不跨过函数的移除和添加
  2. 使用 remember 保存的对象当 Compose 函数被移出组合树后不会保留。
  3. 当 Compose 函数再次被组合进入时,remember 将重新获得一个新的对象。
  4. 要跨组合保持对象,应使用外部状态管理,如 ViewModel。
Android 从传统的XML转到Compose的变化:mutableStateOf、MutableStateFlow;有的使用by,有是用=,有的使用by remember是为什么? 总是被mutableStateOf、MutableStateFlow以及LiveData这些给搞混乱,这里我们就理清一下。如果大家学过传统的XML方式编写界面,然后又学习了Compose,就会发现,他们观察数据变化的对象用的不同了,以前我们用的是LiveData,但换成Compose以后,变成mutableStateOf,但又发现,有些用的是MutableStateFlow,并且,有时候他们赋值的时候,使用by,或者使用by remember,赋值的时候,有时候用=,有时候用value。 阅读详情

相关推荐

Jetpack Compose TextField 状态管理踩坑记:为什么你的输入框内容不更新?

本文深入探讨了Jetpack Compose中TextField状态管理的常见问题与解决方案。通过对比传统EditText与Compose TextField的状态管理机制,详细介绍了使用remember和mutableStateOf的正确方法,以及状态提升、高级控制技巧和表单验证等实战经验,帮助开发者避免常见陷阱,提升开发效率。

weixin_30731305的博客 424

Compose要我们remember,到底怕我们忘了啥?

看过Compose案例或者源码的你,相信肯定是见过remember了的。顾名思义,Compose是要让我们的代码“记住”东西,那到底是记住什么呢?要是不remember,相关功能就实现不了了吗?带着这些问题,来一探究竟吧。...

m0_70749039的博客 1340

Jetpack Compose 中 remember、rememberSaveable、rememberUpdatedState 的使用场景与区别

Jetpack Compose 提供三种状态管理 API:remember 用于临时 UI 状态(如输入框焦点),生命周期与组合一致;rememberSaveable 扩展功能,通过 Bundle 系统在配置变更时保持数据,适合表单等需持久化的简单状态;rememberUpdatedState 专门解决异步操作中的状态过期问题,保持对最新值的引用。选择时需考虑生命周期需求:默认用 remember,持久化用 rememberSaveable,异步场景用 rememberUpdatedState,同时注意避免

文韬武略的专栏 940

Compose remember、mutableStateOf的使用

初学Jetpack Compose遇到的问题,remember、mutableStateOf的使用。

WdbM_的博客 5395

Jetpack Compose状态管理:remember与rememberSaveable对比

状态管理是现代UI开发的核心概念,特别是在声明式UI框架中。Jetpack Compose通过重组机制实现UI更新,当状态变化时自动刷新相关组件。remember和rememberSaveable是Compose中两种关键的状态保持API,它们解决了不同场景下的状态持久化需求。remember适用于临时UI状态管理,而rememberSaveable则能在配置更改后恢复状态,这对移动端开发尤为重要。理解它们的实现原理和生命周期差异,可以帮助开发者构建更健壮的Android应用界面。在实际工程中,合理选择状态

weixin_33937499的博客 480

第158篇 Compose 重组原理:何时执行何时跳过

如果每次重组都传一个新建的 lambda,引用不同 → 参数不稳定 → 子 Composable 逐一重组。解法是。

郑伟强dev的专栏 300

别再乱用remember了!Jetpack Compose状态管理实战避坑指南(附代码对比)

本文深入解析Jetpack Compose中remember和mutableStateOf的正确使用方法,揭示常见性能问题的根源。通过代码对比和实战案例,展示如何避免重组陷阱、优化状态管理策略,并分享与副作用API的协同技巧,帮助开发者提升Compose应用性能。

weixin_30328063的博客 369

compose-remember-preference:Jetpack Compose库,用于持久地记住状态(基于DataStore首选项)

撰写记忆偏好 Jetpack Compose库,用于基于DataStore首选项持久地记住状态。 入门 库通过Maven Central分发。 要使用它,您需要在模块build.gradle添加以下依赖build.gradle : dependencies { implementation ' dev.burnoo:compose-remember-preference:0.3.0 ' } 要在应用程序运行时将状态存储在@Composable ,请使用remember { mutableStateOf(x) } 。 该库具有相同的功能,但支持数据持久性,使用DataStore首选项保存和还原数据。 它具有返回MutableState函数。 @Composable fun Component () { var string by rememberStringPrefer

Compose Performance 高级技巧:深入理解强跳过模式(Strong Skipping Mode)优化原理

Jetpack Compose作为Android平台的现代UI工具包,其性能优化一直是开发者关注的核心。强跳过模式(Strong Skipping Mode)作为Compose性能优化的关键机制,通过精准控制重组范围,显著提升应用响应速度。本文将深入解析强跳过模式的工作原理,帮助开发者掌握这一终极优化技巧。 ## 为什么强跳过模式对Compose性能至关重要? 在传统的命令式UI开发中,开发者

gitblog_00155的博客 467

激光及激光器超全细节&原理总结

本文详细展示了激光、激光器、PN结、半导体激光器、光纤激光器的原理和应用;

guangwulv的博客 5342

前端实现微信扫一扫的思路

本篇文章的关键点就是讲解了我在实现处理多张二维码的场景时的思路,利用canvas遮挡识别过的二维码这个思路是pbk-bin大佬最先想到的,在实现这个需求以后还是很感叹这个思路的巧妙。👏pbk-bin🎁~如果文章对你有帮助,不妨赠人玫瑰,手有余香,预计将会在下篇更新较为完整的微信扫一扫界面和功能。

fang_my的博客 2488

Jetpack Compose重组优化指南:原理、问题与实操

声明式UI框架通过状态驱动界面更新,开发者只需描述UI与状态的关系,框架自动完成刷新。理解其核心更新机制——组合与重组,是优化性能的关键。重组并非重绘,它需要重新执行函数代码并更新描述,若范围失控或参数不稳定,将引发大量无谓计算,导致滚动卡顿与UI闪烁。稳定参数能触发跳过机制,避免子组件重复执行;而频繁新建lambda、状态提升过高等常见问题则会破坏稳定性。合理使用remember缓存计算、derivedStateOf降频合并、@Immutable契约等方式,能让重组范围最小化,提升长列表与高频交互场景的流

weixin_35949153的博客 288

COD论文笔记VSCode: General Visual Salient and Camouflaged Object Detection with 2D Prompt Learning

VSCode模型通过引入领域特定提示和任务特定提示,结合提示区分损失,成功地在单一模型中处理多个显著目标检测和伪装目标检测任务。这种方法不仅提高了模型的性能,还展示了其对未见任务的泛化能力。作者使用 Visual saliency transformer ICCV 2021 作为baseline model这张图展示了VSCode模型的整体框架,特别强调了2D提示学习方法。

985小菜鸡 1625

Android compose测试数据双向绑定

本文演示了使用Jetpack Compose实现数据绑定的方法。通过创建一个待办事项列表应用,展示了Compose的响应式编程特性:1)使用mutableStateOf创建可观察状态变量;2)利用remember保持状态在重组时不丢失;3)实现双向数据绑定 - 文本输入框的值变化自动更新状态变量,状态变化自动触发UI重组。应用包含文本输入、添加按钮和待办列表展示功能,当添加新事项时会更新列表并清空输入框,验证了Compose的数据绑定机制。相比DataBinding,Compose提供了更简洁的声明式UI开

u012116089的博客 131

DDM-MIMO-FMCW雷达速度模糊与解模糊MATLAB仿真

本文深入解析了DDM-MIMO-FMCW雷达中的速度模糊现象及其解模糊方法,通过MATLAB仿真详细展示了相位编码解调、速度扩展算法和混合波形设计三大解决方案。文章还提供了参数配置、信号建模和结果可视化的实用技巧,并分享了工程实践中的避坑指南,帮助开发者高效解决雷达信号处理中的速度模糊问题。

weixin_31528001的博客 347

1688店铺所有商品API接口(整店商品查询API接口)

1688店铺所有商品API接口、1688店铺列表API接口,1688店铺API接口,1688店铺查询商品API接口,1688店铺商品API接口,1688店铺详情接口,1688商品API接口

tbprice的博客 1568

Jetpack Compose 计时器实战:从状态管理到 Canvas 绘制

在 Android 开发向声明式架构演进的过程中,Jetpack Compose 作为官方主推的 UI 工具包,正逐步替代传统 XML 加 View 体系,成为现代应用界面构建的主流选择。其核心技术原理在于组合函数与状态驱动模型:开发者只需描述界面与状态的关系,当状态发生变化时,系统自动触发重组并更新相应 UI。这种范式不仅显著减少样板代码,更提升了动态界面的开发效率与可维护性。在实际工程中,无论是倒计时、进度环还是实时刷新面板,均可依托状态管理、协程调度与 Canvas 绘制能力高效实现。本文便从一个典型

weixin_33824385的博客 314

论文阅读:2024 ACM CCS “Do Anything Now”: Characterizing and Evaluating In-The-Wild Jailbreak Prompts on

大语言模型(LLMs)的滥用问题引起了公众和大语言模型供应商的高度关注。有一种特殊的对抗性提示,叫做越狱提示,它已成为绕过防护措施、让大语言模型生成有害内容的主要攻击手段。在这篇论文中,作者使用新框架JailbreakHub,对2022年12月至2023年12月期间的1405个越狱提示进行了全面分析。作者识别出131个越狱提示社区,发现了越狱提示的独特特征以及主要攻击策略,比如提示注入和权限提升。

CSPhD-winston的博客 1411

Jetpack Compose性能优化实战:避免无效重组的derivedStateOf技巧

本文深入探讨Jetpack Compose中的derivedStateOf技巧,帮助开发者有效避免无效UI重组,提升应用性能。通过实际代码示例,详细解析了derivedStateOf在计数器、列表滚动监听和表单验证等场景的应用,并提供了高级优化建议和常见问题解决方案。

i0j1k2l3m的博客 153

S7-1500——(一)西门子PLC编程从入门到精通4、SCL间接寻址

学习目标是在掌握博途平台SCL编程语言的基本使用基础之上,进一步了解SCL语言环境下的间接寻址过程,初步具备编写复杂控制程序的能力;在编写plc程序过程中, 需要对plc中的数据进行访问,这就是寻址;直接寻址间接寻址;直接寻址直接寻址就是直接对数据的存储单元进行访问;根据表达方式的不同,可分为绝对寻址和符号寻址;对于plc中的标准数据存储区包括IQMTCL以及标准数据块,既可以使用绝对寻址,也可以使用符号寻址;绝对寻址在使用绝对寻址时,可以寻址的宽度包括位,字,节字,双字;

大小曲奇的博客 2121

uniapp - [全端兼容] 详解实现国际化多语言切换全流程及示例,全部页面中英文多语言随意切换即时生效,语言切换全项目立即变化可自定义新增各国其他语言,uniApp实现中英文语言切换完整源码教程!

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,uniapp多语言实现,uni-app项目使用多语言切换功能,中英文切换,uniapp实现中英文语言切换,uniApp实现国际化多语言切换,中文英文之间的更换,Uniapp使用什么插件能支持多种语言,退出后重启依然能让语言保留,设置可切换中英文,uniapp国际化页面双语/顶部导航双语/根据系统语言双语,标题栏文字原生底部菜单tabbar怎么改,使用vue-i18n国际化多国语言,全平台i18n插件,

🏆 前端领域优质创作者 1万+

Jetpack Compose 性能优化完全指南:从重组原理到实战

Jetpack Compose 的性能优化是一个系统工程,需要结合原理理解、代码实践和工具验证。给你的优先级建议(按投入产出比排序):第一步:工具先行。使用找出重组热点,优先解决那些每秒重组超过 10 次的组件。第二步:夯实基础。检查并修正数据类的参数稳定性(添加@Immutable或使用不可变集合),并确保所有LazyColumn都使用了稳定的key。第三步:精益求精。在复杂的动画或滚动场景中,使用和延迟状态读取来优化高频状态。第四步:启动加速。投入半天时间接入,获得立竿见影的启动和滑动性能提升。

天空之城 253

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Compose 性能优化利器:derivedStateOf 核心详解

本文详细介绍了Compose中的derivedStateOf状态加工工具。它通过将高频变化的状态转换为只在关键结果改变时触发的状态,有效减少不必要的重组。文章对比了错误写法与使用derivedStateOf的正确写法,阐明其作为"状态过滤器"的工作原理。同时与remember(key)进行对比,指出derivedStateOf专注于计算结果变化而非依赖项变化。最后列举了滑动监听、表单验证等典型应用场景,并总结其作为"减震器"的核心价值:监控高频状态,仅在结果有意义变化

琦琦的博客 137

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Jetpack Compose重组优化:作用域、稳定性与性能实战

声明式UI框架下,界面由状态驱动,状态变化触发重组。理解重组的最小单位——作用域,以及参数比较依赖的稳定性标记,是优化性能的关键。稳定性不足会导致本应跳过的重组反复执行,造成列表滚动卡顿、界面闪烁等肉眼可见的问题。通过合理设计不可变数据模型、精确控制lambda捕获、善用remember与derivedStateOf,并借助编译期重组报告和Layout Inspector量化问题,开发者可以系统化消除过度重组。本文从重组原理出发,结合典型场景和实测手段,帮助你在实际项目中建立状态变化波及范围的直觉,让Com

weixin_35749796的博客 214

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

彻底理解 Compose remember:从源码到原理

remember的核心职责:在父级作用域中提供稳定存储位置不负责检测变化:变化检测由和Snapshot完成定位不依赖物理位置:通过编译时生成的 Key + 运行时 Anchor 定位底层存储SlotTable使用线性数组 + Gap 机制存储所有状态参数变化检测changed()在重组时比较参数,决定是否重新计算理解rememberAPI 层:简单的缓存接口运行时层:Composer + SlotTable 提供存储和定位响应式层:Snapshot 系统提供变化通知和重组调度。

u012925692的博客 261

15-Compose开发-重组机制

重组 = Compose 自动根据最新状态,重新执行函数以更新 UI 的过程。初始渲染:首次执行函数生成 UI重组:状态变化 → 框架自动重新执行受影响的可组合函数用最新状态刷新 UI,保持数据与视图同步重组不保证一定执行完成重组不保证执行次数最终 UI 一定与最新状态一致不要在可组合函数中执行耗时操作、不可取消任务、副作用逻辑。概念解释重组状态变化时重新执行可组合函数,生成新 UI触发时机状态变化、CompositionLocal 变化、参数变化等智能重组。

weixin_36848576的博客 280
上一篇: 基于 Compose & Canvas 的蛛网图组件开发
下一篇: Compose进阶——在非Compose作用域调用Compose函数
LiePy
博客等级 码龄7年 1927粉丝 33原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值