Kotlin中如何让SharedPreferences的配置修改无需重启APP即可即时生效
配置无法即时生效的根因
你当前的代码仅在MainActivity初始化阶段读取了一次SharedPreferences(以下简称SP)中的小数位数配置,生成对应DecimalFormat实例赋值给sharedViewModel的form属性。后续用户在设置页修改配置后,SP的存储已经通过apply/commit生效,但上层逻辑没有触发重新读取配置、更新form的逻辑,所以变更只能在下次应用启动重新走初始化流程时生效,和存储方法本身无关。
可行解决方案
方案1:监听SP配置变更(侵入性最低)
直接给SP注册变更监听器,只要指定配置项更新就自动刷新格式规则,无需修改设置页逻辑。
- 首先把格式更新逻辑抽为公共方法,避免重复代码:
private fun updateDecimalFormat(places: Int) { sharedViewModel.form = when(places) { 0 -> DecimalFormat("#,###") 1 -> DecimalFormat("#,###.#") 2 -> DecimalFormat("#,###.##") 3 -> DecimalFormat("#,###.###") 4 -> DecimalFormat("#,###.####") else -> DecimalFormat("#,###.##") // 增加默认值兜底,避免空值/非法值崩溃 } // 若需即时刷新当前已渲染的数值,可在此处触发列表/展示控件的刷新逻辑 }
- 在MainActivity中定义SP变更监听器:
private val spChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sp, key -> // 仅响应小数位数配置的变更 if (key == "decimalPlaces") { val decimalPlaces = sp.getString("decimalPlaces", "2") ?: "2" updateDecimalFormat(decimalPlaces.toInt()) } }
- 在onCreate中初始化配置+注册监听器:
val sp = PreferenceManager.getDefaultSharedPreferences(this.applicationContext) // 初始化时读取一次配置 val initPlaces = sp.getString("decimalPlaces", "2") ?: "2" updateDecimalFormat(initPlaces.toInt()) // 注册监听器 sp.registerOnSharedPreferenceChangeListener(spChangeListener)
- 在onDestroy中注销监听器避免内存泄漏:
override fun onDestroy() { super.onDestroy() PreferenceManager.getDefaultSharedPreferences(this.applicationContext) .unregisterOnSharedPreferenceChangeListener(spChangeListener) }
方案2:设置页保存后主动通知更新
如果你的设置页是自定义实现的,可在保存配置时直接通过SharedViewModel触发更新,流程更可控。
- 改造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("#,###.##") } }
- MainActivity初始化时给decimalPlaces赋值初始值:
val sp = PreferenceManager.getDefaultSharedPreferences(this.applicationContext) val initPlaces = sp.getString("decimalPlaces", "2") ?: "2" sharedViewModel.decimalPlaces.value = initPlaces.toInt()
- 设置页保存配置时主动更新变量:
// 设置Fragment中保存配置的逻辑 sp.edit().putString("decimalPlaces", newPlaces.toString()).apply() sharedViewModel.decimalPlaces.postValue(newPlaces)
- 所有使用form做格式化的UI场景,直接observe form的变更自动刷新即可。
优化提示
你原代码中decimalPlaces!!.toInt()的写法存在崩溃风险,若SP中存储的配置为空或非数字会触发空指针/类型转换异常,建议将SP读取的默认值改为"2"而非空字符串,同时增加空安全校验。
内容的提问来源于stack exchange,提问作者ced452
相关产品推荐
相关产品推荐

