Jetpack Compose中Room @Upsert/Update实现:角色更新功能求助
角色更新功能实现方案
核心思路:利用Room的@Upsert统一新增与更新
你的Dao已经定义了@Upsert方法,它会自动根据主键判断操作:
- 若传入的
Character对象主键id为0(新增状态),执行插入 - 若
id为已存在的正数(编辑状态),执行更新
无需单独新增UpdateCharacter事件,只需扩展现有状态与事件逻辑,区分新增/编辑场景即可。
1. 完善状态类(CharacterState)
添加标记编辑状态的字段,用来判断当前是新增还是更新角色:
data class CharacterState( val characterName: String = "", val characterClass: String = "", val characterLevel: Int = 0, val characterKeyAbilityScore: Int = 0, val editingCharacterId: Int = 0 // 0表示新增,非0表示编辑对应ID的角色 )
2. 扩展事件类(CharacterEvent)
新增加载待编辑角色的事件,用于将数据库中的角色数据填充到界面状态:
sealed interface CharacterEvent { object SaveCharacter : CharacterEvent data class SetCharacterName(val characterName: String) : CharacterEvent data class SetCharacterClass(val characterClass: String) : CharacterEvent data class SetCharacterLevel(val characterLevel: Int) : CharacterEvent data class SetCharacterKeyAbilityScore(val score: Int) : CharacterEvent data class LoadCharacterForEdit(val character: Character) : CharacterEvent // 加载待编辑角色 }
3. 修改ViewModel逻辑
更新onEvent方法,处理编辑状态下的角色保存:
fun onEvent(event: CharacterEvent) { when (event) { is CharacterEvent.SaveCharacter -> { val currentState = state.value val name = currentState.characterName val charClass = currentState.characterClass val level = currentState.characterLevel val keyAbility = currentState.characterKeyAbilityScore if (name.isBlank() || charClass.isBlank()) return // 根据编辑状态构建Character对象 val character = if (currentState.editingCharacterId != 0) { // 编辑已有角色:携带原有ID Character( characterName = name, characterClass = charClass, characterLevel = level, characterKeyAbilityScore = keyAbility, id = currentState.editingCharacterId ) } else { // 新增角色:ID用默认0 Character( characterName = name, characterClass = charClass, characterLevel = level, characterKeyAbilityScore = keyAbility ) } // 调用Upsert执行插入/更新 viewModelScope.launch { dao.upsertCharacter(character) } // 重置状态 _state.update { it.copy( characterName = "", characterClass = "", characterLevel = 0, characterKeyAbilityScore = 0, editingCharacterId = 0 ) } } is CharacterEvent.LoadCharacterForEdit -> { // 将待编辑角色的数据填充到状态 _state.update { it.copy( characterName = event.character.characterName, characterClass = event.character.characterClass, characterLevel = event.character.characterLevel, characterKeyAbilityScore = event.character.characterKeyAbilityScore, editingCharacterId = event.character.id ) } } // 处理其他SetXXX事件 is CharacterEvent.SetCharacterName -> { _state.update { it.copy(characterName = event.characterName) } } is CharacterEvent.SetCharacterClass -> { _state.update { it.copy(characterClass = event.characterClass) } } is CharacterEvent.SetCharacterLevel -> { _state.update { it.copy(characterLevel = event.characterLevel) } } is CharacterEvent.SetCharacterKeyAbilityScore -> { _state.update { it.copy(characterKeyAbilityScore = event.score) } } } }
4. 可选:单独使用@Update的方案
如果不想用@Upsert,可以在Dao中新增@Update方法:
@Dao interface CharacterDao{ @Insert suspend fun insertCharacter(character: Character) @Update suspend fun updateCharacter(character: Character) @Delete suspend fun deleteCharacter(character: Character) @Query("SELECT * FROM character ORDER BY characterName COLLATE NOCASE ASC") fun getCharactersOrderedByName(): Flow<List<Character>> }
然后在ViewModel的SaveCharacter分支中手动判断调用:
viewModelScope.launch { if (currentState.editingCharacterId != 0) { dao.updateCharacter(character) } else { dao.insertCharacter(character) } }
内容的提问来源于stack exchange,提问作者IanOro
相关产品推荐
相关产品推荐

