聊聊 compose 的 remember

前言

在前面聊mutableStateOf 的时候用了这段代码来讲述了Compose 状态的更新。

code-1
val name = mutableStateOf("hello compose")
setContent {
    Text(name.value)
}

lifecycleScope.launch {
    delay(3000)
    name.value = "android"
}

接下来,我们继续通过这段代码来一起聊下 Composeremember

浅聊

我们先对code-1的代码稍微做下修改

code-2    
    setContent {
            var name by mutableStateOf("hello compose")
            Text(name)
            //ps:此处代码仅做演示使用,compose中协程的使用并非如此
            lifecycleScope.launch {
                delay(3000)
                name = "android"
            }
     }

当我们这样进行修改之后,发现3s过后,“hello compose” 并没有如期变成“android”。

这是为什么呢? 是协程没有执行吗?还是没有进行重组刷新?用最简单的方法,我们来加日志看一下执行。

code-3   
      setContent {
            Log.i("TAG", "setContent: ")
            var name by mutableStateOf("hello compose")
            Text(name)
            //ps:此处代码仅做演示使用,compose中协程的使用会另做讲解。
            lifecycleScope.launch {
                delay(3000)
                name = "android"
                Log.i("TAG", "launch: ")
            }
        }

可以看到,协程已经执行了,而且也进行了重组刷新,但是为什么值没有改变呢?

这是因为使用变量的组件会被包起来,当变量改变的时候会随之进行重组刷新,每次刷新的时候,就会重新创建一个MutableState对象,这个对象就会取默认值“hello compose”。所以才会看起来每次都进行了刷新,但是文字却没有任何改变。

刷新重组的范围就叫做重组作用域。

我们想让Text() 进行刷新怎么办?可以进行包一层。我们对code-2的代码稍微做下修改。

code-4           
setContent {
           var name by mutableStateOf("hello compose")
           Button(onClick = {}){
               Text(name)
           }
            //ps:此处代码仅做演示使用,compose中协程的使用会另做讲解。
            lifecycleScope.launch {
                delay(3000)
                name = "android"
            }
        }

我们让Button 对他进行一个包裹,然后来看看效果。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I2Jqg2S5-1675173048636)(null)]

可以看到进行包裹了之后,文字发生了改变。虽然这样满足了我们的需求,但是不能每次有使用变量的组件,每次都进行一个包裹吧,这岂不是会疯掉。

接下来就需要有请我们今天的主角 remember了,它就是为了帮助我们解决这个问题。

它可以在每次重组的时候,去帮我们去拿已经缓存的值,不需要每次都是重新创建。

code-5             
setContent {
            var name by remember { mutableStateOf("hello compose") }
            Text(name)
            //ps:此处代码仅做演示使用,compose中协程的使用会另做讲解。
            lifecycleScope.launch {
                delay(3000)
                name = "android"
            }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gpNDjUhs-1675173048669)(null)]

remember 也是一个Composable 函数,因此只能在Composable 中调用。

现在,我们有个场景,我们需要频繁调用某个Compposable, 而且参数大量相同且频繁切换,如果直接用参数进行展示的话,会造成一些不必要的计算。

为了避免不必要的资源浪费,我们也可以使用remember 来解决。

code-6       
        setContent {
            var name by remember { mutableStateOf("hello compose") }
            Column {
                Button(onClick = {
                    val rnds = (0..2).random()
                    name = "随机数:$rnds"
                }) {
                    Text("按钮")
                }
                ShowCharLenth(name)
            }
        }

@Composable
fun ShowCharLenth(value: String) {
    val length = remember { value.getLength() }
    Text("字符串的长度:$length")
}

fun String.getLength(): Int {
    //模仿复杂的计算
    return this.length
}

这样使用,就避免了code-7 中的频繁计算重组。

可是这样还会产生一个问题,如果我们展示的数据发生了变化, 前面的数据进行了缓存,后面的数据即使变了 还会取之前缓存的数据,那直接产生的问题就是数据改变了,但是UI上没有变化。

remember 也早就对这种情况有了解决措施,而且非常简单。

code-8
@Composable
fun ShowCharLenth(value: String) {
    val length = remember(value) { value.getLength() }
    Text("字符串的长度:$length")
}

小括号中的value 就是一个key值,根据key值 再去拿remember缓存的数据,这样就完美解决了我们的问题。

至此,我们从这段很短的代码中学到了 remember 的作用 以及使用,感兴趣的同学可以简单上手实践下。

总结

今天的内容就到这里了,非常的简短,主要就是介绍了一下 remember的作用和使用,希望对于新上手Compose的同学有所帮助。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不说话的匹诺槽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值