在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) } }
代码细节解释
- 默认列表初始化:第一次获取
userAnswers时,如果SavedStateHandle里没有对应数据,就创建一个默认的5个0的列表,同时把它存入SavedStateHandle,确保后续获取的都是同一个状态下的列表; - 索引操作函数:用
getUserAnswerByIndex和setUserAnswerByIndex这两个函数处理带索引的读写,避开属性getter不能带参数的限制; - 触发状态保存:修改列表元素后,用
toMutableList()复制一份新列表(直接传userAnswers也可以,但复制能确保引用变化,让SavedStateHandle明确感知到更新),重新存入SavedStateHandle; - 便捷封装:额外加了
currentUserAnswer属性和updateCurrentUserAnswer函数,直接操作当前选中的currentIndex对应的答案,日常开发用起来更省心。
这样调整后,你就能正常通过索引读写答案列表,而且所有变化都会被SavedStateHandle正确保存,不用担心屏幕旋转这类配置变更导致数据丢失的问题了。
内容来源于stack exchange
相关产品推荐
相关产品推荐

