我想知道是否可以确保 userManager (或 Datastore 等)类中的值不低于 0 且不高于 5。如果没有的话我该怎么办?
class userManager(context: Context) {
private val datastore = context.datastore
companion object {
val NUMBER_OF_LIVES_KEY = intPreferencesKey("number_of_lives")
}
suspend fun setNumberOfLives(numberOfLives: Int){
datastore.edit {
it[NUMBER_OF_LIVES_KEY] = numberOfLives
}
}
val getNumberOfLives: Flow<Int> = datastore.data.map {
if(it[NUMBER_OF_LIVES_KEY]!! > 5){
it[NUMBER_OF_LIVES_KEY] == 5
}
else if(it[NUMBER_OF_LIVES_KEY]!! < 0){
it[NUMBER_OF_LIVES_KEY] == 0
}
it[NUMBER_OF_LIVES_KEY] ?: 5
}
}
我尝试了 if 语句,它给了我一个“java.lang.NullPointerException”错误消息。
https://kotlinlang.org/docs/null-safety.html#the-operator很好地描述了当你使用
!!
时会发生什么:
[...]如果你想要一个NPE,你可以拥有它,但你必须明确要求它,它不会突然出现。
其中 NPE 代表
NullPointerException
,即您遇到的错误。
解决方案很简单:如果您不希望代码因此类异常而中止,请删除
!!
。这样,编译器将首先阻止您编译错误的代码,并强制您在运行之前修复它。
根本问题是您尝试访问的属性不存在。如果应用程序是新安装的或用户擦除了所有数据,这是完全正常的。相反,您想要做的是通过在这种情况下提供默认值来优雅地处理这种情况。实际上,您已经在最后一行代码中执行了此操作,但如果您想事先使用该值,那就太晚了。
现在还有另一个问题,你的 getter 在某些情况下实际上也会保存数据。相反,我建议您将更改首选项值的所有内容移至 setter 方法中:
suspend fun setNumberOfLives(numberOfLives: Int){
datastore.edit {
if (numberOfLives > 5) {
it[NUMBER_OF_LIVES_KEY] == 5
}
else if (numberOfLives < 0) {
it[NUMBER_OF_LIVES_KEY] == 0
}
else {
it[NUMBER_OF_LIVES_KEY] = numberOfLives
}
}
}
这可以大大简化:
suspend fun setNumberOfLives(numberOfLives: Int) {
datastore.edit {
it[NUMBER_OF_LIVES_KEY] = numberOfLives.coerceIn(0, 5)
}
}
现在你的 getter 只检索首选项值并处理不存在的情况:
val getNumberOfLives: Flow<Int> = datastore.data.map {
it[NUMBER_OF_LIVES_KEY] ?: 5
}
这样代码更简洁,不易出错。