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

Kotlin中如何让SharedPreferences的配置修改无需重启APP即可即时生效

配置无法即时生效的根因

你当前的代码仅在MainActivity初始化阶段读取了一次SharedPreferences(以下简称SP)中的小数位数配置,生成对应DecimalFormat实例赋值给sharedViewModel的form属性。后续用户在设置页修改配置后,SP的存储已经通过apply/commit生效,但上层逻辑没有触发重新读取配置、更新form的逻辑,所以变更只能在下次应用启动重新走初始化流程时生效,和存储方法本身无关。

可行解决方案

方案1:监听SP配置变更(侵入性最低)

直接给SP注册变更监听器,只要指定配置项更新就自动刷新格式规则,无需修改设置页逻辑。

  1. 首先把格式更新逻辑抽为公共方法,避免重复代码:
private fun updateDecimalFormat(places: Int) {
    sharedViewModel.form = when(places) {
        0 -> DecimalFormat("#,###")
        1 -> DecimalFormat("#,###.#")
        2 -> DecimalFormat("#,###.##")
        3 -> DecimalFormat("#,###.###")
        4 -> DecimalFormat("#,###.####")
        else -> DecimalFormat("#,###.##") // 增加默认值兜底,避免空值/非法值崩溃
    }
    // 若需即时刷新当前已渲染的数值,可在此处触发列表/展示控件的刷新逻辑
}
  1. 在MainActivity中定义SP变更监听器:
private val spChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sp, key ->
    // 仅响应小数位数配置的变更
    if (key == "decimalPlaces") {
        val decimalPlaces = sp.getString("decimalPlaces", "2") ?: "2"
        updateDecimalFormat(decimalPlaces.toInt())
    }
}
  1. 在onCreate中初始化配置+注册监听器:
val sp = PreferenceManager.getDefaultSharedPreferences(this.applicationContext)
// 初始化时读取一次配置
val initPlaces = sp.getString("decimalPlaces", "2") ?: "2"
updateDecimalFormat(initPlaces.toInt())
// 注册监听器
sp.registerOnSharedPreferenceChangeListener(spChangeListener)
  1. 在onDestroy中注销监听器避免内存泄漏:
override fun onDestroy() {
    super.onDestroy()
    PreferenceManager.getDefaultSharedPreferences(this.applicationContext)
        .unregisterOnSharedPreferenceChangeListener(spChangeListener)
}

方案2:设置页保存后主动通知更新

如果你的设置页是自定义实现的,可在保存配置时直接通过SharedViewModel触发更新,流程更可控。

  1. 改造SharedViewModel,把格式规则改为可观察对象:
// SharedViewModel.kt
val decimalPlaces = MutableLiveData<Int>()
// 小数位数变更时自动生成对应的格式化实例
val form = Transformations.map(decimalPlaces) { places ->
    when(places) {
        0 -> DecimalFormat("#,###")
        1 -> DecimalFormat("#,###.#")
        2 -> DecimalFormat("#,###.##")
        3 -> DecimalFormat("#,###.###")
        4 -> DecimalFormat("#,###.####")
        else -> DecimalFormat("#,###.##")
    }
}
  1. MainActivity初始化时给decimalPlaces赋值初始值:
val sp = PreferenceManager.getDefaultSharedPreferences(this.applicationContext)
val initPlaces = sp.getString("decimalPlaces", "2") ?: "2"
sharedViewModel.decimalPlaces.value = initPlaces.toInt()
  1. 设置页保存配置时主动更新变量:
// 设置Fragment中保存配置的逻辑
sp.edit().putString("decimalPlaces", newPlaces.toString()).apply()
sharedViewModel.decimalPlaces.postValue(newPlaces)
  1. 所有使用form做格式化的UI场景,直接observe form的变更自动刷新即可。
优化提示

你原代码中decimalPlaces!!.toInt()的写法存在崩溃风险,若SP中存储的配置为空或非数字会触发空指针/类型转换异常,建议将SP读取的默认值改为"2"而非空字符串,同时增加空安全校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:51:01