You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决Preferences Datastore存储的值在App重启后重置的问题?

问题分析与修复方案

你的代码存在三个核心问题,导致主题设置无法在重启后保留:

  1. 激活状态未与持久化值同步:isDarkModeActive始终以false为初始值,没有读取Datastore中保存的savedTheme,重启后自然回到默认浅色模式。
  2. 背景颜色判断逻辑错误:使用isDarkModeActive && savedTheme.value的逻辑,只有两个值同时为true才会显示深色,完全不符合需求。
  3. 协程作用域不规范:使用未绑定生命周期的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 08:17:39