Hey Everyone, I successfully toggle between dark t...
# compose
m
Hey Everyone, I successfully toggle between dark theme to light and light to dark, but I facing issue storing to shared preference. Anyone have idea of this
Copy code
setContent {
    val prefViewModel: PrefViewModel = viewModel()
    val mode: Boolean by prefViewModel.mode.observeAsState(false)

    val preferences = getSharedPreferences("AppMode", MODE_PRIVATE)
    val editor = preferences.edit()
    editor.putBoolean("mode", mode)
    editor.apply()

    val prmode = preferences.getBoolean("mode", false)
    
    NewJetpackComposeTheme(darkTheme = prmode) {
        Surface(modifier = Modifier.fillMaxHeight(), color = MaterialTheme.colors.surface) {
            App(prmode, prefViewModel)
        }
    }
}
Copy code
@Composable
fun App(mode: Boolean, prefViewModel: PrefViewModel) {
    val image: Painter = if (mode) {
        painterResource(R.drawable.baseline_light_mode_24)
    } else {
        painterResource(R.drawable.baseline_dark_mode_24)
    }
    Row(
        modifier = Modifier
            .fillMaxSize()
            .padding(top = 10.dp, end = 20.dp),
        horizontalArrangement = Arrangement.End,
    ) {
        IconButton(onClick = { prefViewModel.onModeChange(!mode) }) {
            Icon(
                image,
                "changeAppMode",
            )
        }
        Spacer(modifier = Modifier.size(2.dp))
        Text(modifier = Modifier.padding(top = 12.dp), text = stringResource(R.string.dark_mode))
    }
}
z
It’s not good to write to the preferences from your composable directly. Your ViewModel (or something in the layer even above that) should probably be responsible for managing shared preferences. That said, if you really do want to do it from the composable, use an effect.
❤️ 2
There’s some really good docs about this: https://developer.android.com/jetpack/compose/lifecycle
m
Thanks Dear @Zach Klippenstein (he/him) [MOD]
c
@Zach Klippenstein (he/him) [MOD] you said "your viewModel (or something in the layer even above that)" What would be the layer above that? Or do you just mean some kind of persistence layer abstraction that you work with in your view model?
m
using pref in view model work but recompose not work. Below is setContent code and inside is prefViewModel, it observing state and in getting mode from shared preference. Onclick it change the pref and state of mode. Check the PrefViewModel code below setContent. Please suggest me solution
Copy code
setContent {
    val prefViewModel: PrefViewModel = viewModel()
    val mode: Boolean by prefViewModel.mode.observeAsState(false)
    
    val preferences = getSharedPreferences("AppMode", MODE_PRIVATE)
    var prmode = preferences.getBoolean("mode", false)

    if(prmode.equals(null)) {
        prmode = mode
    }

    NewJetpackComposeTheme(darkTheme = prmode) {
        Surface(modifier = Modifier.fillMaxHeight(), color = MaterialTheme.colors.surface) {
            App(prmode,prefViewModel,preferences,this)
        }
    }
}
Copy code
class PrefViewModel : ViewModel() {
    
    private val _mode = MutableLiveData(false)
    val mode: LiveData<Boolean> = _mode

    fun onModeChange(newMode: Boolean , preferences: SharedPreferences) {
        _mode.value = newMode

        val editor = preferences.edit()
        editor.putBoolean("mode", newMode)
        editor.apply()
    }
}
z
@Colton Idle yea the latter
👍 1
I think that might work, assuming
getSharedPreferences
is cached, but I would move that
getSharedPreferences
call and the
getBoolean
into your view model, do that “if null” logic in the view model, and just expose the actual mode for the composable to use from the view model.
m
okay @Zach Klippenstein (he/him) [MOD] that's good