当前位置:首页 > 谈天说地 > 正文内容

Android开发Compose remember原理解析

34资源网2022年07月30日 10:58214
站长推荐》》》》》摆摊地推这两款软件,一个月3000元-3万元轻松实现《《《《《站长推荐

正文

看过compose案例或者源码的你,相信肯定是见过 remember 了的。顾名思义,compose是要让我们的代码“记住”东西,那到底是记住什么呢?要是不 remember,相关功能就实现不了了吗?

带着这些问题,来一探究竟吧

随机色文本

假设有这么一个“随机底色文本”的需求:实现一个 text,其背景色每次启动都随机产生,且生命周期内不变

用compose可以实现如下:

private val items = arrayof(color.red, color.gray, color.magenta, color.blue, color.green, color.cyan)
@composable
fun 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 = clicked.value + 1
                }
        )
    }
}

text 调用 modifier.background,设置随机从items中取的颜色,每次新的启动,都可能不一样

然而很遗憾,上面的背景色虽然是随机产生,但是单次生命周期里,就可能发生变化 —— 比如点击一下文本,如下图:

更奇怪的是,改变的 clicked 值,并没有如预期一样生效,一直是0……

现象和代码不一?

原因分析

首先,上述代码中的“点击计数” clicked,仅仅是为了测试而存在。因为它是一个 mutablestate 对象,点击后改变其值,会触发recomposition流程,于是组件刷新。这样一来,color 的值将重新由随机函数算出,我们就看到背景色在变化了

同理,虽然我们好像在点击的时候改变了 clicked 的值,希望像view系统一样,界面直接响应响应。但是,因为recomposition的存在,它又被重新构造了,所以其值还是0

正确实现

要实现背景色的整个生命周期固定,但点击文本后,点击计数要更新,应该这么做:

@composable
fun colortext(name: string) {
    val color = remember { items.random() }
    val clicked = remember { mutablestateof(0) }
    //...
}

仅仅将color和clicked由 remember 包裹起来就解决了问题

remember的原理剖析

前面功能的实现,全仗着remember的加持。它究竟是个啥?

我们先从颜色的remember着手,它调用的是这个:

@composable
inline fun <t> remember(calculation: @disallowcomposablecalls () -> t): t =
    currentcomposer.cache(false, calculation)

其注释写明了两个关键点,这也是它的功能描述:

  • 记忆由calculation返回的值,仅在composition中执行
  • 在recomposition过程中,不会重新计算,而是直接返回第1步的值

那么这又是怎么做到的呢?

进一步的相关代码:

@composecompilerapi
inline 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 = block()
            updaterememberedvalue(value)
            value
        } else it
    } as t
}
// 要么返回composer.empty ,要么返回传给updaterememberedvalue的值
@composecompilerapi
fun rememberedvalue(): any?
// 更新调用rememberedvalue()后的值,且此值在下一次调用rememberedvalue()时返回
@composecompilerapi
fun 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的资料请关注萬仟网其它相关文章!

看完文章,还可以用支付宝扫描下面的二维码领取一个支付宝红包,目前可领1-88元不等

支付宝红包二维码

除了扫码可以领取之外,大家还可以(复制 720087999 打开✔支付宝✔去搜索, h`o`n.g.包哪里来,动动手指就能领)。

看下图所示是好多参与这次活动领取红包的朋友:

支付宝红包

扫描二维码推送至手机访问。

版权声明:本文由34楼发布,如需转载请注明出处。

本文链接:https://www.34l.com/post/20058.html

分享给朋友:

相关文章

分享20句非常励志的经典短句
分享20句非常励志的经典短句

1、与其担心未来,不如好好把握现在,不要轻易把梦想寄托在某个人身上,因为未来是你自己的,只有你自己能给自己最大的安全感,无论我们处在人生的那一个阶段,都应努力好好经营自己。2、没有任何一个男人,可以游手好闲赢得女人的欣赏。更没有任何一个女人...

分享10句来自农村的老话名言,句句都很经典
分享10句来自农村的老话名言,句句都很经典

1、家有万贯带毛的不算家里无论都多少畜禽,在未换成钱之前都不叫钱,一场疫情或较大价格波动便成了空。2、富在深山有远亲,穷在闹市无人问人富了,躲到深山老林都有八竿子打不到的亲戚上门拜访;人穷了,离的再近的亲戚都不愿搭理你。3、再穷不卖看家狗,...

上海11月9日又新增一名新冠病毒感染者
上海11月9日又新增一名新冠病毒感染者

上海也不太平啊,据说昨天又新增了一例,这位新冠肺炎感染者是一名51岁的男性,具体请往下看吧。原标题:上海新增1例本地新冠肺炎确诊病例 密切接触者首次核酸检测均为阴性记者11月9日从上海市新冠肺炎疫情防控新闻发布会上获悉,上海市新增1例本地新...

融资丨「镭昱半导体」获千万美元Pre-A轮融资,全彩Micro-LED微显示芯片助力元宇宙发展
融资丨「镭昱半导体」获千万美元Pre-A轮融资,全彩Micro-LED微显示芯片助力元宇宙发展

创业邦获悉,近日,镭昱半导体(Raysolve)宣布完成千万美元Pre-A轮融资,由高榕资本领投,耀途资本跟投,泰合资本担任独家财务顾问。至此,在短短半年内,镭昱半导体完成两轮融资,累计获得投资近亿元人民币。本轮融资将用于公司的全球首款标...

网易云:生而破发,我很抱歉
网易云:生而破发,我很抱歉

图源:摄图网 编者按:本文来自微信公众号财经新知(ID:caijingxinzhi),创业邦经授权转载 云村村长磊磊昨天好忙哦,搞了一个元宇宙的敲钟仪式,但还是阻挡不了破发的命运。 村长昨天敲钟分享的四首歌还记得吗:四次敲锣,四种心境。...

创业前4年无产品,量产一年销售近亿元,这家公司怎么做到的?
创业前4年无产品,量产一年销售近亿元,这家公司怎么做到的?

光子晶体前4年都在死磕产品研发,直到去年才正式量产,目前已实现每月数万平米的光学显示膜出货,销售额近亿元,收获了苹果、亚马逊等合作伙伴,在透明显示领域开了先河。 作者丨解夏 编辑丨及轶嵘 图源丨受访者 “家里的窗户、汽车车窗、公司的玻璃...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。