如何解决Preferences Datastore存储的值在App重启后重置的问题?
问题分析与修复方案
你的代码存在三个核心问题,导致主题设置无法在重启后保留:
- 激活状态未与持久化值同步:
isDarkModeActive始终以false为初始值,没有读取Datastore中保存的savedTheme,重启后自然回到默认浅色模式。 - 背景颜色判断逻辑错误:使用
isDarkModeActive && savedTheme.value的逻辑,只有两个值同时为true才会显示深色,完全不符合需求。 - 协程作用域不规范:使用未绑定生命周期的
CoroutineScope,存在内存泄漏风险,且无法保证协程的生命周期安全。
修复后的代码
第一步:优化ThemeDatastore类(封装key,简化方法)
import android.content.Context import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.preferencesDataStore import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map private val Context.dataStore by preferencesDataStore("ThemeDatastore") class ThemeDatastore(private val context: Context) { private val themeKey = booleanPreferencesKey("Theme") // 直接对外暴露主题流,无需外部传入key val themeFlow: Flow<Boolean> = context.dataStore.data.map { preferences -> preferences[themeKey] ?: false } suspend fun saveTheme(isDark: Boolean) { context.dataStore.edit { preferences -> preferences[themeKey] = isDark } } }
第二步:修正Compose界面逻辑
@Composable fun ThemeToggleScreen() { val context = LocalContext.current // 用remember包裹,避免每次重组创建新的Datastore实例 val themeDatastore = remember { ThemeDatastore(context) } // 收集持久化的主题值 val savedTheme by themeDatastore.themeFlow.collectAsState(initial = false) // 用保存的主题值初始化激活状态 var isDarkModeActive by remember { mutableStateOf(savedTheme) } // 使用绑定Compose生命周期的协程作用域 val coroutineScope = rememberCoroutineScope() // 监听持久化主题的变化,确保UI同步 LaunchedEffect(savedTheme) { isDarkModeActive = savedTheme } // 保存主题的函数 fun saveTheme() { coroutineScope.launch(Dispatchers.IO) { themeDatastore.saveTheme(isDarkModeActive) } } Box( contentAlignment = Alignment.Center, modifier = Modifier .background( color = animateColorAsState( // 直接根据激活状态切换颜色 targetValue = if (isDarkModeActive) Color.DarkGray else Color.White ).value ) .fillMaxSize(), ) { Button(onClick = { isDarkModeActive = !isDarkModeActive saveTheme() }) { Text(text = "Toggle Theme") } } }
关键修改点说明
- 初始化同步:
isDarkModeActive的初始值直接设为savedTheme,启动时自动加载上次保存的主题。 - 状态同步监听:通过
LaunchedEffect监听savedTheme的变化,确保如果其他地方修改了Datastore的值,UI能及时更新。 - 安全协程作用域:
rememberCoroutineScope会绑定当前Composable的生命周期,避免内存泄漏。 - 简化逻辑:Datastore类内部封装key,减少外部传入参数的错误;背景颜色判断直接使用激活状态,逻辑清晰。
内容的提问来源于stack exchange,提问作者Bob Rasner
相关产品推荐
相关产品推荐

