Is this the correct approach to programmatically s...
# compose
f
Is this the correct approach to programmatically switch dark/light theme from a user setting? I just recompose the whole activity (which contains all screens of the app)
Copy code
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val selectedTheme by appPreferencesViewModel.selectedTheme.collectAsState(null)

            selectedTheme?.let { selectedTheme ->
                val darkTheme = when (selectedTheme) {
                    ThemeSelectionValues.LIGHT -> false
                    ThemeSelectionValues.DARK -> true
                    ThemeSelectionValues.SYSTEM -> isSystemInDarkTheme()
                }
                MyAppTheme(darkTheme = darkTheme) {
                    // ActivityBody with NavHost
                }
            }
        }
    }
}
a
If you've set
ThemeSelectionValues.SYSTEM
and you change the system's dark/light mode, I guess it changes correctly? Looks okay to me. That's what I want to do in my next release anyhow.
Unsolicited code clean up since I'm bored...
Copy code
val darkTheme = selectedTheme?.let {
  when (it) {
   ThemeSelectionValues.LIGHT -> false
   ThemeSelectionValues.DARK -> true
   ThemeSelectionValues.SYSTEM -> isSystemInDarkTheme()
  }
} 
MyAppTheme(darkTheme = darkTheme) { 
  //ActivityBody with NavHost
}
f
@adjpd Thank you 👍 Yes it works correctly, I just wasn't sure if recomposing the whole screen was the way to go
@adjpd actually,
MyAppTheme
has to be inside the
?.let
because we need it to be not nullable
a
Consider make
appPreferencesViewModel.selectedTheme
a
StateFlow
so that you get the correct value immediately. Now if the user chose dark theme and the system is in light theme, when you app starts, it will render light theme at first, and then render dark theme immediately after that, which is a waste.
f
@Albert Chang We can't get the theme immediately because DataStore loads the preference asynchronously. Right now I'm not showing the layout at all until the value is loaded (that's why
MyAppTheme
is inside the
?.let
block.