You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:02:06