Compose笔记(十)--DataStore(一)

        这一节主要了解一下Compose中的DataStore,在Jetpack Compose中,DataStore是一种数据存储解决方案,用于以异步、一致的方式存储键值对或自定义类型的数据。它提供了替代SharedPreferences的更现代化、更安全的方案,也是一个基于Flow和Coroutines的异步数据存储解决方案。

 作用:    1 异步操作:避免在主线程上进行阻塞式的 I/O 操作,确保应用的流畅性。2 类型安全:Proto DataStore可以存储自定义的Protocol Buffers消息,提供类型安全的访问。 3 一致性:保证数据的一致性,避免了SharedPreferences可能出现的并发问题。

栗子:

添加依赖:

implementation("androidx.datastore:datastore-preferences:1.1.3")
import android.content.Context
import androidx.datastore.preferences.core.*
import androidx.datastore.preferences.preferencesDataStore


private const val PREFERENCES_NAME = "complex_preferences"

private val Context.dataStore by preferencesDataStore(name = PREFERENCES_NAME)

object PreferencesKeys {
    val USER_NAME = stringPreferencesKey("user_name")
    val USER_AGE = intPreferencesKey("user_age")
    val IS_PREMIUM_USER = booleanPreferencesKey("is_premium_user")
    val FAVORITE_COLORS = stringSetPreferencesKey("favorite_colors")
}
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class PreferencesManager(private val context: Context) {

    
    val userNameFlow: Flow<String?> = context.dataStore.data.map { preferences ->
        preferences[PreferencesKeys.USER_NAME]
    }

    
    val userAgeFlow: Flow<Int?> = context.dataStore.data.map { preferences ->
        preferences[PreferencesKeys.USER_AGE]
    }

    
    val isPremiumUserFlow: Flow<Boolean?> = context.dataStore.data.map { preferences ->
        preferences[PreferencesKeys.IS_PREMIUM_USER]
    }

    
    val favoriteColorsFlow: Flow<Set<String>?> = context.dataStore.data.map { preferences ->
        preferences[PreferencesKeys.FAVORITE_COLORS]
    }

    
    suspend fun saveUserName(name: String) {
        context.dataStore.edit { preferences ->
            preferences[PreferencesKeys.USER_NAME] = name
        }
    }

    
    suspend fun saveUserAge(age: Int) {
        context.dataStore.edit { preferences ->
            preferences[PreferencesKeys.USER_AGE] = age
        }
    }

    
    suspend fun saveIsPremiumUser(isPremium: Boolean) {
        context.dataStore.edit { preferences ->
            preferences[PreferencesKeys.IS_PREMIUM_USER] = isPremium
        }
    }

    
    suspend fun saveFavoriteColors(colors: Set<String>) {
        context.dataStore.edit { preferences ->
            preferences[PreferencesKeys.FAVORITE_COLORS] = colors
        }
    }

    
    suspend fun batchUpdatePreferences(name: String, age: Int, isPremium: Boolean, colors: Set<String>) {
        context.dataStore.edit { preferences ->
            preferences[PreferencesKeys.USER_NAME] = name
            preferences[PreferencesKeys.USER_AGE] = age
            preferences[PreferencesKeys.IS_PREMIUM_USER] = isPremium
            preferences[PreferencesKeys.FAVORITE_COLORS] = colors
        }
    }

    
    suspend fun clearAllPreferences() {
        context.dataStore.edit { preferences ->
            preferences.clear()
        }
    }
}
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

@Composable
fun TestPreferencesScreen() {
    val context = LocalContext.current
    val preferencesManager = remember { PreferencesManager(context) }
    val scope = rememberCoroutineScope()

    
    val userName by preferencesManager.userNameFlow.collectAsState(initial = null)
   
    val userAge by preferencesManager.userAgeFlow.collectAsState(initial = null)
    
    val isPremiumUser by preferencesManager.isPremiumUserFlow.collectAsState(initial = null)
    
    val favoriteColors by preferencesManager.favoriteColorsFlow.collectAsState(initial = null)

    Column(
        modifier = Modifier
           .fillMaxSize()
           .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        
        Text(text = "User Name: ${userName ?: "Not set"}")
        
        Text(text = "User Age: ${userAge ?: "Not set"}")
        
        Text(text = "Is Premium User: ${isPremiumUser ?: "Not set"}")
        
        Text(text = "Favorite Colors: ${favoriteColors?.joinToString() ?: "Not set"}")

        
        Button(onClick = {
            scope.launch {
                preferencesManager.saveUserName("John Doe")
            }
        }) {
            Text(text = "Save User Name")
        }

        
        Button(onClick = {
            scope.launch {
                preferencesManager.saveUserAge(30)
            }
        }) {
            Text(text = "Save User Age")
        }

       
        Button(onClick = {
            scope.launch {
                preferencesManager.saveIsPremiumUser(true)
            }
        }) {
            Text(text = "Save Is Premium User")
        }

        
        Button(onClick = {
            scope.launch {
                preferencesManager.saveFavoriteColors(setOf("Red", "Blue", "Green"))
            }
        }) {
            Text(text = "Save Favorite Colors")
        }

        
        Button(onClick = {
            scope.launch {
                preferencesManager.batchUpdatePreferences(
                    name = "Jane Smith",
                    age = 25,
                    isPremium = false,
                    colors = setOf("Yellow", "Purple")
                )
            }
        }) {
            Text(text = "Batch Update Preferences")
        }

        
        Button(onClick = {
            scope.launch {
                preferencesManager.clearAllPreferences()
            }
        }) {
            Text(text = "Clear All Preferences")
        }
    }
}

分析:TestPreferencesScreen 组件展示了如何在 Compose 中使用 PreferencesManager 来读取和保存偏好设置。通过 collectAsState 方法将 Flow 转换为可观察的状态,当偏好设置发生变化时,界面会自动更新。同时,提供了多个按钮来触发不同的保存和更新操作。

注意:

1 异步操作:DataStore 的所有读写操作都是异步的,需要在协程中进行。在 Compose 中,可以使用rememberCoroutineScope来创建协程作用域。
2 数据迁移:如果从SharedPreferences迁移到 DataStore,需要手动实现数据迁移逻辑。
3 避免在同一进程中为给定文件创建多个DataStore实例:这可能会导致数据不一致或冲突。
4 DataStore的通用类型必须是不可变的:这有助于确保数据的完整性和一致性。
5 不要为同一文件混合使用SingleProcessDataStore和MultiProcessDataStore:这同样可能会导致数据不一致或冲突。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值