繁体   English   中英

Lambda function 用作输入参数导致重组

[英]Lambda function used as input argument causes recomposition

考虑下面的片段

fun doSomething(){
}

@Composable
fun A() {
    Column() {
        val counter = remember { mutableStateOf(0) }
        B {
            doSomething()
        }
        Button(onClick = { counter.value += 1 }) {
            Text("Click me 2")
        }
        Text(text = "count: ${counter.value}")
    }
}

@Composable
fun B(onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("click me")
    }
}

现在当按下“点击我 2”按钮时,B compose function 将被重新组合,尽管它里面没有任何改变。

说明 doSomething 用于演示目的。 如果你坚持要有一个实际的例子,你可以考虑下面 B 的用法:

B{
    coroutinScope.launch{
        bottomSheetState.collapse()
        doSomething()
    }
}

我的问题:

  1. 为什么这个 lamda function 导致重组
  2. 修复它的最佳方法

我对这个问题的理解

从 compose 编译器报告中我可以看到 B 是一个可跳过的 function 并且输入 onClick 是稳定的。 起初我虽然是因为 lambda function 在每次重组 A 时都会重新创建,并且它与之前的不同。 而这种差异会导致B的重组。但这不是真的,因为如果我在lambda function内部使用其他东西,比如改变state,它不会导致重组。

我的解决方案

  1. 尽可能使用委托。 像 viewmode::doSomething 或 ::doSomething。 不幸的是,它并不总是可能的。
  2. 使用 lambda function 里面记住:
val action = remember{
    {
        doSomething()
    }
}
B(action)

看起来很难看 =) 3- 以上的组合。

当您点击Button “Click me 2”时, A可组合项会因为Text(text = "count: ${counter.value}")而重新组合。 发生这种情况是因为它重组了正在读取可以更改的值的 scope。

如果您使用的是:

B {
    Log.i("TAG","xxxx")
}

单击Button “Click me 2”不会重新组合 B 可组合项。

如果您正在使用

B{
    coroutinScope.launch{
        Log.i("TAG","xxxx")
    }
}

B 可组合项被重组。

当读取 State 时,它会触发最近的 scope 中的重组。而 scope 是未标记内联并返回 Unit 的 function。
要使用coroutinScope ,您必须使用rememberCoroutineScope ,它是一个可组合的内联 function。 inline可组合函数的主体被简单地复制到它们的调用站点,这些函数没有自己的重组范围。

为避免它,您可以使用:

B {
    Log.i("TAG","xxxx")
}

@Composable
fun B(onClick: () -> Unit) {
    val scope = rememberCoroutineScope()
   
    Button(
        onClick = {
            scope.launch {
                onClick()
            }
        }
    ) {
        Text(
            "click me ",
        )
    }
}

来源和学分:

您可以使用第 2 篇博文中描述的LogCompositions可组合项来检查代码中的重组。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM