我正在尝试构建一个简单的应用程序,通过使用数据类将所有值导入到可组合项中,从而更容易重构。
所有值都已成功传递。但是,每当我尝试将功能添加到可组合项中时,尽管没有显示错误,但它不起作用。
这是包含主要活动和标题为“Test1”的可组合项的文件 它显示一个文本小部件,上面写着红色字体的“Hello World”,其下方有一个蓝色按钮。
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Test1(Test1Properties(
textProperties = TextProperties(),
buttonProperties = ButtonProperties()
),
Test1Functions())
}
}
}
@Composable
fun Test1(
test1Properties: Test1Properties,
test1Functions: Test1Functions
){
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxSize()
) {
Text(
text = test1Properties.textProperties.text,
color = test1Properties.textProperties.color,
fontSize = test1Properties.textProperties.fontSize,
fontWeight = test1Properties.textProperties.fontWeight
)
Button(
onClick = {test1Functions.changeTextPropertiesText(test1Properties)},
colors = ButtonDefaults.buttonColors(
containerColor = test1Properties.buttonProperties.containerColor
)
) {
Text(text = test1Properties.buttonProperties.text)
}
}
}
这是包含所有数据类的文件,这些数据类保存了可组合项的所有值。 共有三个数据类。一个用于文本小部件,一个用于按钮,一个用于将它们全部组合在一起。有一个类保存可组合项的功能,称为“Test1Functions”。它只有一个功能,将文本小部件的颜色更改为蓝色。
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
data class Test1Properties(
val textProperties: TextProperties,
val buttonProperties: ButtonProperties
)
data class TextProperties(
var text: String = "Hello World",
var color: Color = Color.Red,
val fontSize: TextUnit = 30.sp,
val fontWeight: FontWeight = FontWeight.Bold
)
data class ButtonProperties(
val onClick: () -> Unit = {},
val text: String = "Button",
val containerColor: Color = Color.Blue
)
class Test1Functions {
fun changeTextPropertiesText(test1Properties: Test1Properties): Color {
test1Properties.textProperties.color = Color.Blue
return test1Properties.textProperties.color
}
}
一切看起来都很好,没有发生错误,但是当按下按钮时,预期的功能没有发生。预期的功能是将文本小部件中的文本变成蓝色。
如果您对这种构建应用程序的方式有任何问题,请推荐更好的方法。
这种方法有几个问题。
首先,这不会按预期工作,因为可组合项应响应的每个更改状态(例如设置文本颜色)都必须可由 Compose 运行时观察到。这只适用于
MutableState
对象。但在开始将所有数据类的属性包装在 MutableState 中之前,我建议您重新考虑整个方法。
我认为您想要做的是拥有一个集中位置,您可以在其中定义可组合项的默认值。因此,属性从一开始就不应该是可变的。
但即便如此,仍然违背了 Compose 工作原理的核心原则:每个可组合项都应该是独立的,只有变量作为参数传递。这可以实现更好的可重用性并简化可组合性。如果您想重用
Test1
,您首先需要创建一个可以传递的复杂对象,而大多数数据可能不会被更改。
相反,请使参数类型尽可能简单:您只需要一个字符串作为文本。 fontSize 和 fontWeight 在运行时可能永远不会改变。至于颜色:这些“可以”因多种原因而改变:表示不同的按钮状态(启用/禁用、当前正在激活)、切换到深色主题等等。但幸运的是,所有这些都有内置支持,因此您不必自己传递颜色值。您想要的是自定义您的Material Theme。 甚至文本字符串也不应该定义为文字,它应该从
字符串资源动态读取,具体取决于应用程序用户选择的语言。 我实际上会完全放弃数据类并做这样的事情:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyAppTheme {
Test1()
}
}
}
}
@Composable
fun Test1(
displayText: String = stringResource(R.string.hello_world),
buttonText: String = stringResource(R.string.button),
initialColor: Color = MaterialTheme.colorScheme.primary,
) {
var textColor by remember { mutableStateOf(initialColor) }
val otherTextColor = MaterialTheme.colorScheme.tertiary
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxSize(),
) {
Text(
text = displayText,
color = textColor,
fontSize = 30.sp,
fontWeight = FontWeight.Bold,
)
Button(
onClick = { textColor = otherTextColor },
colors = ButtonDefaults.buttonColors(containerColor = Color.Blue),
) {
Text(text = buttonText)
}
}
}
当您在 Android Studio 中创建新项目时,可以使用Empty Activity
作为模板。它包含预定义的自定义材料主题,您可以复制并根据自己的喜好进行调整。
@Composable
fun Test1(
test1Functions: Test1Functions
){
val test1Properties by remember {
mutableStateOf( test1Functions.test)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
modifier = Modifier
.fillMaxSize()
) {
Text(
text = test1Properties.textProperties.value.text,
color = test1Properties.textProperties.value.color,
fontSize = test1Properties.textProperties.value.fontSize,
fontWeight = test1Properties.textProperties.value.fontWeight
)
Button(
onClick = {test1Functions.changeTextPropertiesText(test1Properties)},
colors = ButtonDefaults.buttonColors(
containerColor = test1Properties.buttonProperties.containerColor
)
) {
Text(text = test1Properties.buttonProperties.text)
}
}
}
data class Test1Properties(
val textProperties: MutableState<TextProperties>,
val buttonProperties: ButtonProperties
)
data class TextProperties(
var text: String = "Hello World",
var color: Color = Color.Red,
val fontSize: TextUnit = 30.sp,
val fontWeight: FontWeight = FontWeight.Bold
)
data class ButtonProperties(
val onClick: () -> Unit = {},
val text: String = "Button",
val containerColor: Color = Color.Blue
)
class Test1Functions {
val test = Test1Properties(
textProperties = mutableStateOf(TextProperties()),
buttonProperties = ButtonProperties()
)
fun changeTextPropertiesText(test1Properties: Test1Properties) {
test.textProperties.value = test.textProperties.value.copy(
color = Color.Blue
)
}
}
您可以在https://developer.android.com/develop/ui/compose/state
阅读有关状态的更多信息 您还可以完善代码,例如用于查看模型、适当的状态管理等。