【问题标题】:Avoid default values in Androids SharedPreferences避免在 Androids SharedPreferences 中使用默认值
【发布时间】:2021-04-09 12:41:24
【问题描述】:

SharedPreferences 提供以下函数来检索字符串:

String getString(String key, @Nullable String defValue);

存储 Int 时,默认值不可为空:

int getInt(String key, int defValue);

我现在正在寻找存储和检索可为空的Int?,例如:

var timerDuration: Int?
    get() = prefs.getIntOrNull(TIMER_DURATION)
    set(value) { prefs.edit { putIntOrNull(TIMER_DURATION, value) } }

解决方案一:当value为null时,移除key

private fun SharedPreferences.getIntOrNull(key: String) =
    if (prefs.contains(key)) {
        getInt(key, 12345)
    } else {
        null
    }

private fun SharedPreferences.Editor.putIntOrNull(key: String, value: Int?) =
    if (value == null) {
        remove(key)
    } else {
        putInt(key, value)
    }

...但我不确定由于共享首选项的异步特性,我是否会遇到多个快速访问的问题?


解决方案 2:对所有内容都使用字符串选项:

private fun SharedPreferences.getIntOrNull(key: String) =
    prefs.getString(key, null)?.toIntOrNull()

private fun SharedPreferences.Editor.putIntOrNull(key: String, value: Int?) =
    putString(key, value?.toString())

...但是.toIntOrNull() 感觉这样一个简单的任务需要很多开销?


我为什么要这样做?

我希望 Kotlin Multiplattform 允许我将 iOS 版本添加到我现有的 Android 应用程序中。 我的目标是完全用 Kotlin 编写的“核心”模块,没有特定于平台的依赖项。 “核心”则只使用这个接口,由 Android & iOS - Apps 实现

interface SettingsStorage {

    var timerDuration: Int?

    [...]
}

因为我不希望有重复的默认值逻辑我喜欢在我的“核心”模块中处理它


还有其他(更好的)选择吗?我觉得我在重新发明轮子......

【问题讨论】:

    标签: android kotlin kotlin-multiplatform-mobile


    【解决方案1】:

    您的任何一种方法都可以。 SharedPreferences 是线程安全的。只有当您在清单中设置服务以在单独的进程中运行并且它与您的应用程序的其余部分同时修改首选项时,选项 1 才会真正失败。这不是你会意外做的事情。

    您的第二种方法没有任何额外的开销,因为在后台,SharedPreferences 都是字符串,因此您的代码基本上与SharedPreferences.getInt 做同样的事情,除了当首选项不存在时返回默认值或不能被解析为 Int。

    【讨论】:

      【解决方案2】:

      当您将 Int 存储到 SharedPreferences 时,它在内部存储为字符串。因此,为了获取,只需获取一个字符串,如果它是 null 则返回它,或者尝试将其解析为 Int。设置时,只需将您的 Int 转换为 String 并使用 putString 方法放置即可。

      var timerDuration: Int?
          get() = try { prefs.getString(TIMER_DURATION, null)?.toInt() } catch (e: Exception) { null }
          set(value) { prefs.edit { putString(TIMER_DURATION, value.toString()) } }
      

      【讨论】:

      • 这不是和我的解决方案#2一样吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-21
      • 2020-08-03
      • 1970-01-01
      相关资源
      最近更新 更多