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

在SavedStateHandle中存储可变列表并通过索引编辑其值的实现疑问

在SavedStateHandle中存储可变列表并通过索引编辑其值的实现疑问

看起来你是想在QuizViewModel里用SavedStateHandle保存用户的答题列表,还得能通过索引读写对应位置的答案对吧?先帮你梳理下当前代码里的问题,再给你一套可行的实现方案。

首先你原来的userAnswers属性写法有两个明显的问题:

  • Kotlin的属性getter不能接收参数,你写的get(currentIndex)这种语法根本跑不通,属性getter只能无参返回对应值;
  • setter里用field = value也不对,因为你没初始化这个field的初始值,而且我们的状态是存在SavedStateHandle里的,不该用field来缓存。

那正确的实现思路应该怎么调整呢?

核心注意点

因为MutableList是引用类型,你直接修改列表里的元素时,SavedStateHandle是感知不到变化的——它只会在你重新把整个列表设置进去的时候才会持久化更新。所以修改元素后一定要记得把列表重新存回SavedStateHandle。

具体代码实现

class QuizViewModel(private val savedStateHandle: SavedStateHandle) : ViewModel() {
    private companion object {
        const val CURRENT_INDEX_KEY = "current_index"
        const val USER_ANSWERS_KEY = "user_answers"
        // 预设默认答案列表长度,你可以根据需求调整
        const val DEFAULT_ANSWER_COUNT = 5
    }

    // currentIndex的实现没问题,保留即可
    private var currentIndex: Int
        get() = savedStateHandle.get(CURRENT_INDEX_KEY) ?: 0
        set(value) = savedStateHandle.set(CURRENT_INDEX_KEY, value)

    // 从SavedStateHandle获取答案列表,不存在就初始化默认值并存入
    private val userAnswers: MutableList<Int>
        get() = savedStateHandle.get<MutableList<Int>>(USER_ANSWERS_KEY) 
            ?: MutableList(DEFAULT_ANSWER_COUNT) { 0 }.also {
                savedStateHandle.set(USER_ANSWERS_KEY, it)
            }

    // 通过索引获取答案,处理索引越界的情况
    fun getUserAnswerByIndex(index: Int): Int {
        return userAnswers.getOrElse(index) { 0 }
    }

    // 通过索引设置答案
    fun setUserAnswerByIndex(index: Int, answer: Int) {
        if (index in userAnswers.indices) {
            // 修改列表元素
            userAnswers[index] = answer
            // 重新存入SavedStateHandle,触发状态持久化
            savedStateHandle.set(USER_ANSWERS_KEY, userAnswers.toMutableList())
        }
    }

    // 额外封装:直接操作当前索引的答案,日常用起来更顺手
    val currentUserAnswer: Int
        get() = getUserAnswerByIndex(currentIndex)

    fun updateCurrentUserAnswer(answer: Int) {
        setUserAnswerByIndex(currentIndex, answer)
    }
}

代码细节解释

  1. 默认列表初始化:第一次获取userAnswers时,如果SavedStateHandle里没有对应数据,就创建一个默认的5个0的列表,同时把它存入SavedStateHandle,确保后续获取的都是同一个状态下的列表;
  2. 索引操作函数:用getUserAnswerByIndex和setUserAnswerByIndex这两个函数处理带索引的读写,避开属性getter不能带参数的限制;
  3. 触发状态保存:修改列表元素后,用toMutableList()复制一份新列表(直接传userAnswers也可以,但复制能确保引用变化,让SavedStateHandle明确感知到更新),重新存入SavedStateHandle;
  4. 便捷封装:额外加了currentUserAnswer属性和updateCurrentUserAnswer函数,直接操作当前选中的currentIndex对应的答案,日常开发用起来更省心。

这样调整后,你就能正常通过索引读写答案列表,而且所有变化都会被SavedStateHandle正确保存,不用担心屏幕旋转这类配置变更导致数据丢失的问题了。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:14:30