[英]Dumb recomposition in Android Compose
Consider this minimal code snippet (in Kotlin):考虑这个最小的代码片段(在 Kotlin 中):
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import java.time.LocalDateTime
import java.util.*
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var time by remember {
mutableStateOf("time")
}
Column(modifier = Modifier.clickable { time = LocalDateTime.now().toString() }) {
Text(text = UUID.randomUUID().toString())
Text(text = time)
}
}
}
}
Examining the above code, from a logical perspective, one expects that upon clicking the Column
, since only the parameter time
changes, only the lower time Text
composable would be redrawn.检查上面的代码,从逻辑的角度来看,人们期望在单击Column
时,由于只有参数time
发生变化,因此只有较低 time 的Text
composable 会被重绘。 This is because recomposition skips as much as possible .这是因为重组尽可能地跳过。
However, one finds that the upper Text
composable is being redrawn too (the displayed UUID keeps changing).然而,人们发现上面的Text
composable 也在重绘(显示的 UUID 不断变化)。
Notice that the non-idempotence of my Column
composable should have no bearing unless the redraw is dumb.请注意,除非重绘是愚蠢的,否则我的Column
可组合的非幂等性应该没有影响。
You can try running this block of code您可以尝试运行此代码块
@Composable
fun IdempotenceTest() {
var time by remember {
mutableStateOf("time")
}
Column(
modifier = Modifier.clickable {
time = LocalDateTime.now().toString()
}
) {
Text(text = getRandomUuid())
TestComposable(text = returnSameValue())
Text(text = time)
}
}
@Composable
fun TestComposable(text: String) {
SideEffect {
Log.d(TAG, "TestComposable composed with: $text")
}
Text(text = text)
}
private fun getRandomUuid(): String {
Log.d(TAG, "getRandomUuid: called")
return UUID.randomUUID().toString()
}
private fun returnSameValue(): String {
Log.d(TAG, "returnSameValue: called")
return "test"
}
If you check the logs, you will see that everytime the Column
recomposes, the compiler will call the getRandomUuid
and returnSameValue
function and based on the value returned by these, it will decide whether or not to re-compose.如果查看日志,您会看到每次Column
重组时,编译器都会调用getRandomUuid
和returnSameValue
function 并根据这些返回的值决定是否重组。 If you want to prevent a calculation from happening again and again, wrap it in a remember{}
block.如果您想防止一次又一次地发生计算,请将其包装在一个remember{}
块中。
As a side-note, the Composable functions must be side-effect free to ensure idempotence.作为旁注,可组合函数必须是无副作用的,以确保幂等性。 You can read more here你可以在这里阅读更多
rememberSavable {...}
worked for me. rememberSavable {...}
为我工作。
It allows you to update the state, directly from clickable
and trigger recomposition:它允许您直接从clickable
和触发重组更新 state:
...
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
...
var time by rememberSaveable { mutableStateOf("time") }
Column(
modifier = Modifier.clickable {
time = LocalDateTime.now().toString()
}
) {
Text(text = UUID.randomUUID().toString())
Text(text = time)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.