Jetpack Compose中那些离奇的重组情况,你遇到了吗?

缘起

真正使用Compose做线上项目还是在两年前了,详见这篇文章《直播、聊天交友APP的开发及上架GooglePlay总结【Compose版】》,文章地址在:https://juejin.cn/post/7042181171706331150。去年由于职位的变动移交给了面向海外的团队人员开发,后来虽然没有专门做Compose的项目了,但是自己写Android端示例项目或者桌面端项目的时候都会第一选择Compose来进行开发。

最近海外组的小伙伴做复盘的时候发现一件离奇的事情,Compose的“重组”在有些情况下没有按照预想的来,是我们预想不对呢?还是出现了其它隐形的影响重组的因素呢?官方说的所有函数类型(lambda)是稳定的类型到底靠不靠谱呢?

注: 该文章基于Compose 1.3.0版本编写,其它版本暂未进行实验。

场景复现

首先我们要把遇到的问题重新复现出来,这种情况也是费了我九牛二虎之力,由于思维的惯性以及多年没有继续深耕Compose,说多了都是泪。

主要的UI效果很简单,第一层是一个Text和一个Box组件,Text组件中的文本数量跟随下层Button组件的点击次数不断增加,Box组件也添加了点击事件,点击也可使得数字增加。

Snipaste_2023-06-28_16-32-27.png

场景类Activity如下所示,已将部分代码精简处理,注意其中的mTemp变量,虽然全局都没有使用它。我们主要需要关注的是 WrapperBox() 函数,它包含了一个Modifier参数和函数类型的参数,按官方的说法来说应该是不会重组的:

class SceneActivity : ComponentActivity() {
   
   

    private val mCurrentNum = mutableStateOf(0)

    // 这个注释打开、关闭会影响WrapperBox进行重组
    // private var mTemp = "Hello"

    override fun onCreate(savedInstanceState: Bundle?) {
   
   
        super.onCreate(savedInstanceState)
        setContent {
   
   
            Column {
   
   
                Row {
   
   
                    Text(
                        text = "当前数量:${
     
     mCurrentNum.value}",
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(26.dp)
                            .weight(1f)
                            .colorBg()
                    )

                    WrapperBox(
                        modifier = Modifier
                            .fillMaxWidth()
                            .height(26.dp)
                            .weight(1f),
                        onClick = {
   
   
                            mCurrentNum.value++
                        })
                }

                Button(onClick = {
   
    mCurrentNum.value++ }) {
   
   
                    Text(text = "点击增加数量")
                }
            }
        }
    }

    @Composable
    private fun WrapperBox(
        modifier: Modifier,
        onClick: () -> Unit
    ) {
   
   
        Box(
            modifier = modifier
                .clickable {
   
   
                    onClick.invoke()
                }
                .colorBg()
        )
    }
}

// 扩展的随机背景色修饰符,每次重组都会显示不同颜色
fun Modifier.colorBg() = this
    .background(
        color = randomComposeColor(),
        shape = RoundedCornerShape(4.dp)
    )
    .padding(4.dp)

直接给大家看下不同场景下的效果:

  • 没有mTemp变量的时候

scrcpy1.gif
可以看到,点击按钮的时候,只有左侧的文本组件在重组,文本在跟随点击的数量不断更新,这个情况跟我们所认为的情况是一样的

  • 有mTemp变量的时候

scrcpy2.gif
这个时候除了左侧的文本组件在不断重组,右侧的Box组件居然也在不断重组(变换颜色)。

为什么多了一个变量就会导致原本不会重组的组件发生重组呢?我们分别看下反编译后的源码,已做部分删减处理:

  • 没有mTemp变量的时候
public final class SceneActivity extends ComponentActivity {
   
   
    public static final int $stable = 0;

    public void onCreate(Bundle bundle) {
   
   
        super.onCreate(bundle);
    
        // ...省略代码
        Modifier weight$default = RowScope.weight$default(rowScopeInstance, SizeKt.m473height3ABfNKs(SizeKt.fillMaxWidth$default(Modifier.Companion, 0.0f, 1, null), Dp.m4662constructorimpl(f2)), 1.0f, false, 2, null);
        composer.startReplaceableGroup(1157296644);
        ComposerKt.sourceInformation(composer, "C(remember)P(1):Composables.kt#9igjgp");
        boolean changed = composer.changed(sceneActivity);
        Object rememberedValue = composer.rememberedValue();
        if (changed || rememberedValue == Composer.Companion.getEmpty()) {
   
   
            rememberedValue = (Function0) new Function0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值