Kotlin中Settings Fragment切换暗黑模式时lateinit变量未初始化问题求助
问题根源
首次切换主题后,AppCompatDelegate.setDefaultNightMode会触发Activity自动重建,原Fragment持有的lateinit var activity: MainActivity指向的是已销毁的旧Activity,重建后的新Fragment未重新初始化这个变量,导致二次点击时抛出未初始化异常。另外直接持有Activity强引用还存在内存泄漏风险。
解决方案
方案1:避免持有Activity引用,动态获取当前关联的Activity
删除Fragment中的lateinit var activity: MainActivity字段,在点击事件中直接获取当前有效的Activity实例:
class SettingsFragment : PreferenceFragmentCompat() { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) val themePreference: Preference = findPreference("theme")!! themePreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { // 安全转换为MainActivity并调用方法 (activity as? MainActivity)?.setTheme() true } } }
如果能确保Fragment始终依附于MainActivity,也可以用requireActivity()强制转换:
(requireActivity() as MainActivity).setTheme()
方案2:在Fragment生命周期中重新赋值Activity(不推荐,存在强引用风险)
如果一定要保留lateinit变量,在Fragment与Activity重新关联时更新变量值:
class SettingsFragment : PreferenceFragmentCompat() { private lateinit var activity: MainActivity override fun onAttach(context: Context) { super.onAttach(context) // 每次关联Activity时重新赋值 activity = context as MainActivity } override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) val themePreference: Preference = findPreference("theme")!! themePreference.onPreferenceClickListener = Preference.OnPreferenceClickListener { activity.setTheme() true } } }
关于直接调用setTheme/applyStyle无效的说明
AppCompat的夜间模式是全局控制的,必须通过AppCompatDelegate.setDefaultNightMode方法切换,直接调用Activity的setTheme或getTheme().applyStyle无法触发全局夜间模式的切换逻辑,所以不会生效。
内容的提问来源于stack exchange,提问作者Grimlock
相关产品推荐
相关产品推荐

