Android Jetpack Compose:如何让ItemSkillView获取StatsField输入数据
解决方案
1. 修复StatsField的状态更新逻辑
你当前代码里所有StatsField的onValueChange都调用skillViewModel.updateStrenghtValue(it),这会导致只有力量值被更新,敏捷、体质等其他属性从未被正确赋值。需要为每个属性绑定对应的ViewModel更新方法:
修改CharacterSkillScreen中的循环逻辑:
statsField.forEach { (label, value) -> StatsField( label = label, value = value.toString(), onValueChange = { newValue -> when(label) { "FOR" -> skillViewModel.updateStrenghtValue(newValue) "DEX" -> skillViewModel.updateDexterityValue(newValue) "CON" -> skillViewModel.updateConstitutionValue(newValue) "INT" -> skillViewModel.updateIntelligenceValue(newValue) "SAG" -> skillViewModel.updateWisdomValue(newValue) "CHA" -> skillViewModel.updateCharismValue(newValue) } }, modifier = Modifier.weight(1f) ) }
2. 完善SkillViewModel的状态管理
确保SkillViewModel包含所有属性的状态,并提供初始化方法,用来接收导航传递的初始值:
class SkillViewModel : ViewModel() { private val _uiState = MutableStateFlow(SkillUiState()) val uiState = _uiState.asStateFlow() // 用导航参数初始化状态 fun initializeStats( strength: String, dexterity: String, constitution: String, intelligence: String, wisdom: String, charism: String ) { _uiState.update { it.copy( strenght = strength, dexterity = dexterity, constitution = constitution, intelligence = intelligence, wisdom = wisdom, charism = charism ) } } // 各属性的单独更新方法 fun updateStrenghtValue(value: String) { _uiState.update { it.copy(strenght = value) } } fun updateDexterityValue(value: String) { _uiState.update { it.copy(dexterity = value) } } fun updateConstitutionValue(value: String) { _uiState.update { it.copy(constitution = value) } } fun updateIntelligenceValue(value: String) { _uiState.update { it.copy(intelligence = value) } } fun updateWisdomValue(value: String) { _uiState.update { it.copy(wisdom = value) } } fun updateCharismValue(value: String) { _uiState.update { it.copy(charism = value) } } // 保留原有updateSkillTitle等方法 fun updateSkillTitle(title: String) { _uiState.update { it.copy(skillTitle = title) } } } data class SkillUiState( val strenght: String = "", val dexterity: String = "", val constitution: String = "", val intelligence: String = "", val wisdom: String = "", val charism: String = "", val skillTitle: String = "" )
3. 在CharacterSkillScreen中初始化ViewModel状态
添加LaunchedEffect,页面加载时用导航参数初始化SkillViewModel的初始值:
@Composable fun CharacterSkillScreen( strenghtValue: String? = "", dexterityValue: String? = "", constitutionValue: String? = "", intelligenceValue: String? = "", wisdomValue: String? = "", charismValue: String? = "", skillViewModel: SkillViewModel = viewModel() ) { val addedSkill = remember { mutableStateListOf<@Composable () -> Unit>() } val skillUiState by skillViewModel.uiState.collectAsState() // 初始化状态 LaunchedEffect(Unit) { skillViewModel.initializeStats( strenghtValue.orEmpty(), dexterityValue.orEmpty(), constitutionValue.orEmpty(), intelligenceValue.orEmpty(), wisdomValue.orEmpty(), charismValue.orEmpty() ) } // 保留原有Column、LazyColumn等代码... }
4. 在ItemSkillView中直接获取状态值
现在可以在ItemSkillView中直接从skillViewModel.uiState读取所有属性值,比如使用敏捷值:
@OptIn(ExperimentalMaterial3Api::class) @Composable fun ItemSkillView( skillViewModel: SkillViewModel = viewModel(), resultActionPoints: String = "0" ) { val uiState by skillViewModel.uiState.collectAsState() var isExpanded by remember { mutableStateOf(false) } Column( modifier = Modifier .fillMaxWidth() .clickable { isExpanded = !isExpanded } .animateContentSize() ) { // 示例:显示当前敏捷值 Text(text = "当前敏捷值:${uiState.dexterity}") // 保留原有ConstraintLayout、TextField等代码... } }
问题根源说明
- 之前所有
StatsField都只更新力量值,导致其他属性从未被写入ViewModel,自然无法获取 - 未用导航参数初始化
SkillViewModel的初始状态,进入页面时属性为空 - 使用
CharacterViewModel时可能因为作用域不匹配(属于不同导航图),无法共享状态,而SkillViewModel是当前页面专属ViewModel,作用域匹配可正确共享状态
内容的提问来源于stack exchange,提问作者Olhm.exe
相关产品推荐
相关产品推荐

