UserPreferencesDataSource

Data source for managing user preferences using DataStore (Proto DataStore pattern).

This interface provides type-safe access to user preferences stored via Jetpack DataStore. Unlike SharedPreferences, DataStore offers:

  • Type safety through Protocol Buffers (Proto DataStore)

  • Reactive updates via Flow

  • Coroutine support for all operations

  • Data consistency with transactional updates

  • Crash safety with atomic read/write operations

Design Pattern

This follows the DataStore Pattern:

  • All reads return Flow for reactive UI updates

  • All writes are suspend functions (transactional and async)

  • Preferences are strongly typed via UserDataPreferences

  • No blocking I/O operations

Common Use Cases

  1. Store user session data (user ID, profile info)

  2. Manage UI preferences (theme, dynamic colors)

  3. Persist app settings that survive app restarts

  4. Track onboarding state or first-run flags

Usage in Repositories

class UserRepository @Inject constructor(
private val userPreferencesDataSource: UserPreferencesDataSource
) {
// Reactive query for UI
fun observeUserData(): Flow<UserData> =
userPreferencesDataSource.getUserDataPreferences()
.map { it.toDomainModel() }

// Check authentication
suspend fun requireUserId(): String =
userPreferencesDataSource.getUserIdOrThrow()

// Update theme
suspend fun setDarkMode(enabled: Boolean): Result<Unit> = suspendRunCatching {
val config = if (enabled) DarkThemeConfigPreferences.DARK
else DarkThemeConfigPreferences.LIGHT
userPreferencesDataSource.setDarkThemeConfig(config)
}
}

Usage in ViewModels

@HiltViewModel
class SettingsViewModel @Inject constructor(
private val userPreferencesDataSource: UserPreferencesDataSource
) : ViewModel() {
val userData = userPreferencesDataSource.getUserDataPreferences()
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), UserDataPreferences())

fun toggleDarkMode() {
_uiState.updateWith {
val newConfig = when (userData.value.darkThemeConfigPreferences) {
DarkThemeConfigPreferences.LIGHT -> DarkThemeConfigPreferences.DARK
DarkThemeConfigPreferences.DARK -> DarkThemeConfigPreferences.LIGHT
DarkThemeConfigPreferences.FOLLOW_SYSTEM -> DarkThemeConfigPreferences.DARK
}
userPreferencesDataSource.setDarkThemeConfig(newConfig)
}
}
}

Threading

All suspend functions execute on IO dispatcher automatically (handled by DataStore). Callers should not wrap calls with withContext.

See also

for the preferences data model

for user profile data

Functions

Link copied to clipboard

Observes the complete user preferences data.

Link copied to clipboard
abstract suspend fun getUserIdOrThrow(): String

Retrieves the authenticated user's ID, or throws if user is not authenticated.

Link copied to clipboard
abstract suspend fun resetUserPreferences()

Resets all user preferences to their default values.

Link copied to clipboard
abstract suspend fun setDarkThemeConfig(darkThemeConfigPreferences: DarkThemeConfigPreferences)

Updates the dark theme configuration preference.

Link copied to clipboard
abstract suspend fun setDynamicColorPreference(useDynamicColor: Boolean)

Updates the dynamic color preference.

Link copied to clipboard
abstract suspend fun setUserProfile(preferencesUserProfile: PreferencesUserProfile)

Updates the user's profile information in preferences.