如何在 Jetpack Compose 中使用外部函数更改数据类变量值?

问题描述 投票:0回答:2

我正在尝试构建一个简单的应用程序,通过使用数据类将所有值导入到可组合项中,从而更容易重构。

所有值都已成功传递。但是,每当我尝试将功能添加到可组合项中时,尽管没有显示错误,但它不起作用。

这是包含主要活动和标题为“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
    }
}

一切看起来都很好,没有发生错误,但是当按下按钮时,预期的功能没有发生。预期的功能是将文本小部件中的文本变成蓝色。

如果您对这种构建应用程序的方式有任何问题,请推荐更好的方法。

function android-jetpack-compose data-class
2个回答
0
投票

这种方法有几个问题。

首先,这不会按预期工作,因为可组合项应响应的每个更改状态(例如设置文本颜色)都必须可由 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

作为模板。它包含预定义的自定义材料主题,您可以复制并根据自己的喜好进行调整。


0
投票

@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

阅读有关状态的更多信息 您还可以完善代码,例如用于查看模型、适当的状态管理等。

© www.soinside.com 2019 - 2024. All rights reserved.