Android Studio主题切换与SharedPreferences持久化存储问题
问题描述
尝试在ActionBar添加主题切换选项,支持浅色/深色主题切换,并用SharedPreferences持久化设置以实现重启后保留主题。未添加SharedPreferences前可正常切换主题,添加后功能失效。
问题根源分析
- 存储Key不统一:切换浅色/深色主题时分别使用
"light"和"dark"两个独立Key存储,导致读取时无法准确获取当前选中的主题配置 - 读取逻辑混乱:读取主题时的判断条件与存储逻辑不匹配,取值逻辑存在错误
- 主题设置时机错误:在
setContentView()之后调用AppCompatDelegate.setDefaultNightMode(),主题切换不会生效,必须在加载布局前完成主题设置
修复方案
步骤1:统一SharedPreferences存储Key
切换主题时使用同一个Key(例如"selected_theme")存储当前选中的主题模式值,替代原有分Key存储的逻辑。
步骤2:修正主题读取与设置逻辑
在onCreate()中,先从SharedPreferences读取主题配置,在setContentView()之前完成主题设置,确保布局加载时使用正确的主题。
修正后的代码示例
MainActivity.kt 菜单点击逻辑修改
override fun onOptionsItemSelected(item: MenuItem): Boolean { val editor = App.sharedPreferences.edit() when(item.itemId){ R.id.menuRead -> { Toast.makeText(this,"Pulling data from Room",Toast.LENGTH_SHORT).show() } R.id.menuDelete -> { Toast.makeText(this,"Deleting data from Room",Toast.LENGTH_SHORT).show() viewModel.deleteData() } R.id.lightTheme -> { Toast.makeText(this,"Switching to Light Theme!",Toast.LENGTH_SHORT).show() val lightMode = AppCompatDelegate.MODE_NIGHT_NO AppCompatDelegate.setDefaultNightMode(lightMode) editor.putInt("selected_theme", lightMode) editor.apply() } R.id.darkTheme -> { Toast.makeText(this,"Switching to Dark Theme!",Toast.LENGTH_SHORT).show() val darkMode = AppCompatDelegate.MODE_NIGHT_YES AppCompatDelegate.setDefaultNightMode(darkMode) editor.putInt("selected_theme", darkMode) editor.apply() } } return true }
MainActivity.kt onCreate逻辑修改
class MainActivity : AppCompatActivity() { private lateinit var binding: ActivityMainBinding private val viewModel : MainViewModel by viewModels() private val defaultTheme = AppCompatDelegate.MODE_NIGHT_NO override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 读取主题配置并设置,必须在setContentView之前执行 val savedTheme = App.sharedPreferences.getInt("selected_theme", defaultTheme) AppCompatDelegate.setDefaultNightMode(savedTheme) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // 其他原有业务逻辑... } }
额外优化建议
- 可在Application类中定义主题相关常量,避免重复硬编码模式值
- 若主题切换后未自动生效,可手动调用
recreate()重启当前Activity(部分场景下setDefaultNightMode会自动触发重启,无需额外操作)
内容的提问来源于stack exchange,提问作者MoeS
相关产品推荐
相关产品推荐

