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

Android Room事务实现多选Todo上移一行的高效稳健方案

多选中Todo上移的Room事务高效实现方案

核心思路

根据你的需求和示例,核心逻辑是将选中的Todo按原顺序前置,未选中的Todo按原顺序后置,重新分配连续的orderId,同时通过Room事务保证操作的原子性,避免数据不一致。

实现步骤与代码

  1. Dao层方法定义
    先在TodoDao中补充必要的查询和更新方法:

    @Dao
    interface TodoDao {
        // 获取所有按orderId升序排列的Todo
        @Query("SELECT * FROM todo ORDER BY orderId ASC")
        suspend fun getAllTodosOrdered(): List<Todo>
    
        // 单个更新Todo的orderId
        @Query("UPDATE todo SET orderId = :newOrderId WHERE id = :todoId")
        suspend fun updateTodoOrder(todoId: Long, newOrderId: Int)
    
        // 事务方法:实现多Todo上移
        @Transaction
        suspend fun moveUp(todos: List<Todo>) {
            if (todos.isEmpty()) return
    
            // 1. 获取全量有序Todo列表
            val fullOrderedList = getAllTodosOrdered()
            val selectedIds = todos.map { it.id }.toSet()
    
            // 2. 拆分选中/未选中列表,保留各自原顺序
            val selectedTodos = fullOrderedList.filter { selectedIds.contains(it.id) }
            val unselectedTodos = fullOrderedList.filter { !selectedIds.contains(it.id) }
    
            // 3. 合并成新的顺序列表:选中项前置,未选中项后置
            val newOrderedList = selectedTodos + unselectedTodos
    
            // 4. 批量更新(仅更新orderId变化的项)
            newOrderedList.forEachIndexed { index, todo ->
                val newOrderId = index + 1 // orderId从1开始计数
                if (todo.orderId != newOrderId) {
                    updateTodoOrder(todo.id, newOrderId)
                }
            }
        }
    }
    
  2. 实体类优化
    给orderId添加唯一约束,避免出现重复排序值:

    @Entity(indices = [Index(value = ["orderId"], unique = true)])
    data class Todo(
        @PrimaryKey val id: Long,
        val orderId: Int,
        val extra: String
    )
    

方案优势

  • 高效性:仅更新orderId发生变化的Todo,而非全量更新,减少数据库IO操作。
  • 稳健性:通过Room的@Transaction保证操作原子性,要么全部更新成功,要么回滚,避免出现部分更新导致的排序混乱。
  • 边界处理:自动处理空选中列表、选中全部Todo、选中项已在最前等边界情况,无需额外判断。

逻辑验证(匹配你的示例)

初始全量列表:[32(1),25(2),21(3),33(4),37(5)]
选中列表:[32(1),21(3),33(4)]
未选中列表:[25(2),37(5)]
合并后新列表:[32,21,33,25,37]
重新分配orderId后:

  • 32: 1(无变化,不更新)
  • 21: 2(原3→2,更新)
  • 33:3(原4→3,更新)
  • 25:4(原2→4,更新)
  • 37:5(无变化,不更新)
    最终结果完全匹配你的预期。

内容的提问来源于stack exchange,提问作者bilabila

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 11:53:14