### Observe Preferences with get() Source: https://context7.com/patrykandpatrick/opto/llms.txt Demonstrates how to retrieve preference values as a reactive Flow. Shows usage in a ViewModel to expose state to Compose UI and how to collect updates. ```kotlin import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch class SettingsViewModel(private val preferences: AppPreferences) : ViewModel() { val darkModeEnabled: StateFlow = preferences.isDarkMode .get() .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = false ) init { viewModelScope.launch { preferences.userName.get().collect { name -> println("User name changed to: $name") } } } } @Composable fun SettingsScreen(viewModel: SettingsViewModel) { val isDarkMode by viewModel.darkModeEnabled.collectAsState() Switch( checked = isDarkMode, onCheckedChange = { viewModel.toggleDarkMode() } ) } ``` -------------------------------- ### Synchronous Preference Retrieval with get(Preferences) in Kotlin Source: https://context7.com/patrykandpatrick/opto/llms.txt Explains the `get(preferences: Preferences)` method in `PreferenceImpl` for synchronously extracting preference values from a `Preferences` snapshot. This is useful for atomic reads of multiple preferences within a DataStore transaction. ```kotlin import androidx.datastore.preferences.core.Preferences import kotlinx.coroutines.flow.first class BatchPreferenceReader(private val preferences: AppPreferences) { // Read multiple preferences from a single snapshot suspend fun getSettingsSummary(): String { val snapshot: Preferences = preferences.dataStore.data.first() val isDark = preferences.isDarkMode.get(snapshot) val userName = preferences.userName.get(snapshot) val notifCount = preferences.notificationCount.get(snapshot) return "User: $userName, Dark Mode: $isDark, Notifications: $notifCount" } // Use within DataStore data flow for consistent reads fun observeAllSettings() = preferences.dataStore.data.map { SettingsState( isDarkMode = preferences.isDarkMode.get(it), userName = preferences.userName.get(it), notificationCount = preferences.notificationCount.get(it) ) } } data class SettingsState( val isDarkMode: Boolean, val userName: String, val notificationCount: Int ) ``` -------------------------------- ### Install Opto via Gradle Source: https://context7.com/patrykandpatrick/opto/llms.txt Instructions for adding the Opto library to an Android project using JitPack. Includes dependencies for both the core implementation and the domain module. ```kotlin // settings.gradle.kts dependencyResolutionManagement { repositories { maven { url = uri("https://jitpack.io") } } } // build.gradle.kts (app module) dependencies { implementation("com.github.patrykandpatrick.opto:core:1.2.0") // Optional: domain module only (for multi-module projects) implementation("com.github.patrykandpatrick.opto:domain:1.2.0") } ``` -------------------------------- ### Implement PreferenceManager for DataStore Source: https://context7.com/patrykandpatrick/opto/llms.txt Defines a custom preference holder class by implementing the PreferenceManager interface. This setup connects the class to the Android DataStore and defines typed preference keys. ```kotlin import android.content.Context import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.patrykandpatrick.opto.core.PreferenceManager private val Context.dataStore: DataStore by preferencesDataStore(name = "settings") class AppPreferences(context: Context) : PreferenceManager { override val dataStore: DataStore = context.dataStore val isDarkMode = preference( key = booleanPreferencesKey("dark_mode"), defaultValue = false ) val userName = preference( key = stringPreferencesKey("user_name"), defaultValue = "Guest" ) val notificationCount = preference( key = intPreferencesKey("notification_count"), defaultValue = 0 ) } ``` -------------------------------- ### Atomic Preference Updates with update() in Kotlin Source: https://context7.com/patrykandpatrick/opto/llms.txt Demonstrates how to use the `update()` suspend function for atomic preference modifications, preventing race conditions. It shows examples for incrementing/decrementing counters and appending to string values. ```kotlin import kotlinx.coroutines.launch class NotificationViewModel(private val preferences: AppPreferences) : ViewModel() { fun incrementNotificationCount() { viewModelScope.launch { preferences.notificationCount.update { currentCount -> currentCount + 1 } } } fun decrementNotificationCount() { viewModelScope.launch { preferences.notificationCount.update { currentCount -> maxOf(0, currentCount - 1) } } } fun appendToUserName(suffix: String) { viewModelScope.launch { preferences.userName.update { currentName -> "$currentName$suffix" } } } } ``` -------------------------------- ### Custom Serialization with preference() in Kotlin Source: https://context7.com/patrykandpatrick/opto/llms.txt Illustrates custom serialization and deserialization for storing complex types in DataStore using the `preference()` method. It covers enums, JSON-encoded objects, and comma-separated lists. ```kotlin import androidx.datastore.preferences.core.stringPreferencesKey import com.patrykandpatrick.opto.core.PreferenceManager import kotlinx.serialization.encodeToString import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json // Define a custom data class @Serializable data class UserSettings( val theme: String = "system", val fontSize: Int = 14, val notificationsEnabled: Boolean = true ) // Define an enum enum class AppTheme { LIGHT, DARK, SYSTEM } class AppPreferences(context: Context) : PreferenceManager { override val dataStore: DataStore = context.dataStore // Enum preference with serialization val appTheme = preference( key = stringPreferencesKey("app_theme"), defaultValue = AppTheme.SYSTEM, serialize = { it.name }, deserialize = { AppTheme.valueOf(it) } ) // Complex object preference using JSON serialization val userSettings = preference( key = stringPreferencesKey("user_settings"), defaultValue = UserSettings(), serialize = { Json.encodeToString(it) }, deserialize = { Json.decodeFromString(it) } ) // List preference stored as comma-separated string val favoriteIds = preference( key = stringPreferencesKey("favorite_ids"), defaultValue = emptyList(), serialize = { ids -> ids.joinToString(",") }, deserialize = { str -> if (str.isBlank()) emptyList() else str.split(",").map { it.toInt() } } ) } // Usage class ThemeViewModel(private val preferences: AppPreferences) : ViewModel() { val currentTheme: StateFlow = preferences.appTheme .get() .stateIn(viewModelScope, SharingStarted.Eagerly, AppTheme.SYSTEM) fun setTheme(theme: AppTheme) { viewModelScope.launch { preferences.appTheme.set(theme) } } fun addFavorite(id: Int) { viewModelScope.launch { preferences.favoriteIds.update { ids -> if (id !in ids) ids + id else ids } } } } ``` -------------------------------- ### Update Preferences with set() Source: https://context7.com/patrykandpatrick/opto/llms.txt Utilizes the suspend set() function to persist new values to DataStore. This ensures thread-safe writes within coroutine scopes. ```kotlin import kotlinx.coroutines.launch class SettingsViewModel(private val preferences: AppPreferences) : ViewModel() { fun toggleDarkMode() { viewModelScope.launch { preferences.isDarkMode.get().first().let { current -> preferences.isDarkMode.set(!current) } } } fun updateUserName(newName: String) { viewModelScope.launch { preferences.userName.set(newName) } } fun resetNotificationCount() { viewModelScope.launch { preferences.notificationCount.set(0) } } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.