温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android开发Compose remember原理是什么

发布时间:2022-07-29 13:53:21 来源:亿速云 阅读:153 作者:iii 栏目:开发技术

本篇内容主要讲解“Android开发Compose remember原理是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android开发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生命周期不变 &mdash;&mdash; 即类似普通值的状态一致性

  • MutableState对象所存储的实际值,可变 &mdash;&mdash; 这用以触发Recomposition,并且获取更新值

到此,相信大家对“Android开发Compose remember原理是什么”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI