Search code examples
androidkotlinkotlin-coroutinesandroid-jetpack-datastore

Data store preferences is not working with Kotlin and Coroutines


I have a problem with data store preferences. I trying to save chosen database mode and display the current one in the settings screen, but I don't know why it's not working. I don't have any errors. I tried debugging the code, but the debugger is not going into the coroutine block.

class SettingsRepository @Inject constructor(
    private val dataStore: DataStore<Preferences>
) {
    val databaseMode: Flow<String?>
        get() =
            dataStore.data.map { preferences ->
                preferences[DATABASE_MODE_KEY]
            }

    suspend fun updateDatabaseMode(databaseMode: String) {
        dataStore.edit { preferences ->
            preferences[DATABASE_MODE_KEY] = databaseMode
        }
    }

    companion object {
        val DATABASE_MODE_KEY = stringPreferencesKey("database_mode")
    }
}
@HiltViewModel
class SettingsViewModel @Inject constructor(
    private val settingsRepository: SettingsRepository
) : ViewModel() {
    private val _settingsState = MutableStateFlow(SettingsState())
    var settingsState: StateFlow<SettingsState> = _settingsState.asStateFlow()

    init {
        viewModelScope.launch {
            settingsRepository.databaseMode.map { mode ->
                _settingsState.update {
                    it.copy(
                        databaseMode = mode ?: DatabaseMode.LOCAL.name
                    )
                }
            }
        }
    }

    fun onChangeDatabaseMode(databaseMode: String) {
        viewModelScope.launch {
            settingsRepository.updateDatabaseMode(databaseMode)
        }
        _settingsState.update {
            it.copy(
                databaseMode = databaseMode,
                showDatabaseModeDropdown = false
            )
        }
    }
[...]

I want to save the chosen database mode and display the current one.


Solution

  • As I can see in you code databaseMode flow is never collected so map in init block never called.

    I would suggest using combine for databaseMode and settingsState flows in this case.

    Something like this:

    val databaseModeFlow = settingsRepository.databaseMode
    val combinedFlow = settingsState.combine(databaseMode){ s, d ->
        s.copy(databaseMode = d)
    }
    

    And init block should be removed.