为什么有时没有记住的 mutableStateOf 也能工作?

Bie*_*Dav 11 kotlin android-jetpack-compose mutablestateof

我一直在使用 Jetpack Compose Desktop。我注意到一些我真的不明白的事情:

import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application

@Composable
@Preview
fun App() {
    var text by mutableStateOf("Hello, World!")

    MaterialTheme {
        TextField(text, onValueChange = { text = it })
        Button(onClick = {
            text = "Hello, Desktop!"
        }) {
            Text(text)
        }
    }
}

fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        App()
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么我可以更改 中的文本TextField?我认为在每次重组时,可变状态都会使用初始值重新实例化:所以Text应该无法更改

import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application

@Composable
@Preview
fun App() {
    var text by mutableStateOf("Hello, World!")

    Column {
        TextField(text, onValueChange = { text = it })
        Button(onClick = {
            text = "Hello, Desktop!"
        }) {
            Text(text)
        }
    }
}

fun main() = application {
    Window(onCloseRequest = ::exitApplication) {
        App()
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您将 替换MaterialTheme为 a,Column它会突然按预期工作,并且您无法更改 中的文本TextField

这是为什么?这是一个错误还是一个功能?

Thr*_*ian 15

这是 Compose 的一个关于范围界定和智能重组的功能。你可以在这里查看我的详细回答。

真正让你的整个Composable重构是Column使用inline关键字定义的。

@Composable
inline fun Column(
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: @Composable ColumnScope.() -> Unit
) {
    val measurePolicy = columnMeasurePolicy(verticalArrangement, horizontalAlignment)
    Layout(
        content = { ColumnScopeInstance.content() },
        measurePolicy = measurePolicy,
        modifier = modifier
    )
}
Run Code Online (Sandbox Code Playgroud)

假设您有一个Composable在合成时最初设置背景颜色,并在每次重新合成时更改它,从而创建自己的范围。没有的 lambdainline被视为范围。

@Composable
fun RandomColorColumn(content: @Composable () -> Unit) {

    Column(
        modifier = Modifier
            .padding(4.dp)
            .shadow(1.dp, shape = CutCornerShape(topEnd = 8.dp))
            .background(getRandomColor())
            .padding(4.dp)
    ) {
        content()
    }
}
Run Code Online (Sandbox Code Playgroud)

@Composable
fun App2() {
    var text by mutableStateOf("Hello, World!")

    RandomColorColumn {
        TextField(text, onValueChange = { text = it })
        Button(onClick = {
            text = "Hello, Desktop!"
        }) {
            Text(text)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个与Column

@Composable
fun App() {
    var text by mutableStateOf("Hello, World!")

    Column(modifier = Modifier.background(getRandomColor())) {
        TextField(text, onValueChange = { text = it })
        Button(onClick = {
            text = "Hello, Desktop!"
        }) {
            Text(text)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

随机颜色功能

fun getRandomColor() =  Color(
    red = Random.nextInt(256),
    green = Random.nextInt(256),
    blue = Random.nextInt(256),
    alpha = 255
)
Run Code Online (Sandbox Code Playgroud)

您将看到每次更改文本时列背景颜色都会更改,但不会更改App2()

在此输入图像描述