I designed a theme settings fragment to let user choose between themes . It writes values to a Preferences Datastore which this then observed by the ViewModel's observer and theme is changed accordingly. However when I try to switch from System default to Dark mode, the observer goes in a loop. This is how my code for the observer looks like:
viewModel.userPreferences.observe(viewLifecycleOwner) { theme ->
Log.d(TAG, theme.toString())//-> to know which value is in the Preferences
when (theme) {
AppCompatDelegate.MODE_NIGHT_NO -> lightThemeButton.isChecked = true
AppCompatDelegate.MODE_NIGHT_YES -> darkThemeButton.isChecked = true
AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM -> followSystemButton.isChecked =
true
AppCompatDelegate.MODE_NIGHT_AUTO_BATTERY -> batterySaverButton.isChecked = true
}
}
This is the logcat when I try to switch from Follow System to Dark mode:
2021-04-29 01:13:28.162 14075-14075/com.istemanipal.lumos D/ThemeFragment: 2
2021-04-29 01:13:28.170 14075-14075/com.istemanipal.lumos D/ThemeFragment: -1
2021-04-29 01:13:28.181 14075-14075/com.istemanipal.lumos D/ThemeFragment: 2
2021-04-29 01:13:28.188 14075-14075/com.istemanipal.lumos D/ThemeFragment: -1
2021-04-29 01:13:28.196 14075-14075/com.istemanipal.lumos D/ThemeFragment: 2
2021-04-29 01:13:28.207 14075-14075/com.istemanipal.lumos D/ThemeFragment: -1
2021-04-29 01:13:28.215 14075-14075/com.istemanipal.lumos D/ThemeFragment: 2
This goes in an infinite loop. For reference I am storing User Preferences as AppCompatDelegate's constants(cause that way I can just call AppCompatDelegate setDefaultNightMode exactly). I am running an Android 10 Device with the Dark Mode applied system wide.
Code used for changing the theme:
//setup on click listeners for each radio button
binding.lightThemeButton.setOnCheckedChangeListener { _, isChecked ->
viewModel.changeTheme(AppCompatDelegate.MODE_NIGHT_NO)
}
binding.darkThemeButton.setOnCheckedChangeListener { _, isChecked ->
viewModel.changeTheme(AppCompatDelegate.MODE_NIGHT_YES)
}
binding.followSystemButton.setOnCheckedChangeListener { _, isChecked ->
viewModel.changeTheme(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
}
Finally the MainActivity does this:
userPreferencesViewModel.userPreferences.observe(this) {
AppCompatDelegate.setDefaultNightMode(it)
}