正文 看过compose案例或者源码的你,相信肯定是见过 remember 了的 。顾名思义,compose是要让我们的代码“记住”东西,那到底是记住什么呢?要是不 remember,相关功能就实现不了了吗?
带着这些问题,来一探究竟吧
随机色文本 假设有这么一个“随机底色文本”的需求:实现一个 text,其背景色每次启动都随机产生,且生命周期内不变
用compose可以实现如下:
private val items = arrayof(color.red, color.gray, color.magenta, color.blue, color.green, color.cyan)@composablefun colortext(name: string) {val color = items.random()val clicked = mutablestateof(0)log.d("ct", "ui compose")column {text(text = "i'm colored: ${clicked.value}", modifier = modifier.padding(16.dp).background(color).clickable {log.d("ct", "clicked")clicked.value = https://baike.zhangchenghui.com/517296/clicked.value + 1})}}text 调用 modifier.background,设置随机从items中取的颜色,每次新的启动,都可能不一样
然而很遗憾,上面的背景色虽然是随机产生,但是单次生命周期里,就可能发生变化 —— 比如点击一下文本,如下图:
更奇怪的是,改变的 clicked 值,并没有如预期一样生效,一直是0……
现象和代码不一?
原因分析 首先,上述代码中的“点击计数” clicked,仅仅是为了测试而存在 。因为它是一个 mutablestate 对象,点击后改变其值,会触发recomposition流程,于是组件刷新 。这样一来,color 的值将重新由随机函数算出,我们就看到背景色在变化了
同理,虽然我们好像在点击的时候改变了 clicked 的值,希望像view系统一样,界面直接响应响应 。但是,因为recomposition的存在,它又被重新构造了,所以其值还是0
正确实现 要实现背景色的整个生命周期固定,但点击文本后,点击计数要更新,应该这么做:
@composablefun colortext(name: string) {val color = remember { items.random() }val clicked = remember { mutablestateof(0) }//...}
仅仅将color和clicked由 remember 包裹起来就解决了问题
remember的原理剖析 前面功能的实现,全仗着remember的加持 。它究竟是个啥?
我们先从颜色的remember着手,它调用的是这个:
@composableinline fun <t> remember(calculation: @disallowcomposablecalls () -> t): t =currentcomposer.cache(false, calculation)其注释写明了两个关键点,这也是它的功能描述:
- 记忆由
calculation返回的值,仅在composition中执行 - 在recomposition过程中,不会重新计算,而是直接返回第1步的值
进一步的相关代码:
@composecompilerapiinline fun <t> composer.cache(invalid: boolean, block: () -> t): t {@suppress("unchecked_cast")return rememberedvalue().let {// 无效或empty值时,走if流程,计算并保存值,否则直接返回// remember传入的invalid为false,所以肯定走值判断if (invalid || it === composer.empty) {val value = https://baike.zhangchenghui.com/517296/block()updaterememberedvalue(value)value} else it} as t}// 要么返回composer.empty,要么返回传给updaterememberedvalue的值@composecompilerapifun rememberedvalue(): any?// 更新调用rememberedvalue()后的值,且此值在下一次调用rememberedvalue()时返回@composecompilerapifun updaterememberedvalue(value: any?)interface composer {// ....companion object {/*** 用于标记无值的状态*/val empty = object {override fun tostring() ="empty"}}}从上述代码注释中,基本上已经对原理很清楚了,简单地说就是:
- 由composer作为存储控制
- 无值时,走初始化逻辑并返回值,同时存储该值;有值时,直接返回已存储的值
其实如出一辙,只是点击计数remember的,不是普通值,而是一个
mutablestate 类型 。这样一来,它就有两层含义了:- mutablestate对象本身在整个composition生命周期不变 —— 即类似普通值的状态一致性
- mutablestate对象所存储的实际值,可变 —— 这用以触发recomposition,并且获取更新值
小结
remember 的存在,其实就是 compose 机制下的产物,用以解决recomposition时的值恢复问题 。而因为它的“值不变”特性,还可以用来解决耗时计算的问题,即,耗时计算被remember了,那它就只会执行一次,避免了不必要的额外开销【Android开发Compose remember原理解析】以上就是android开发compose remember原理解析的详细内容,更多关于android开发compose remember的资料请关注www.887551.com其它相关文章!
-- 展开阅读全文 --
推荐阅读
- 孩子生日祝福语朋友圈 三岁孩子生日祝福语朋友圈
- 总参谋长相当于古代什么官
- 圆 WPF实现环形菜单的示例代码
- 蒙山县美食
- 法兰绒怎么清洗 法兰绒怎么洗才好?法兰绒正确的洗涤方法
- Flutter实现资源下载断点续传的示例代码
- 什么是马甲线马甲线指的是什么
- 涿怎么读 涿的读法
- Flutter实现顶部导航栏功能
