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

如何在ViewModel中使用SharedPreferences中存储的数值

ViewModel 中使用 SharedPreferences 的正确实现方案

核心原则:禁止在 ViewModel 中持有 Activity、Fragment 等 View 层级的 Context 引用,避免页面销毁时无法回收引发内存泄漏,仅可使用全局 Application 级别的 Context 操作 SharedPreferences。

方案1:使用 AndroidViewModel(最简实现,适合中小项目)

AndroidViewModel 是 ViewModel 的官方子类,内部默认持有全局 Application 上下文,不存在内存泄漏风险,不需要额外处理 Context 传递逻辑。

import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import androidx.lifecycle.AndroidViewModel

class LocaleViewModel(application: Application) : AndroidViewModel(application) {
    companion object {
        private const val PREFERENCES_NAME = "app_config"
        private const val KEY_LOCALE = "current_locale"
    }

    // 直接通过Application Context获取SharedPreferences
    private val preferences: SharedPreferences by lazy {
        getApplication<Application>().getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
    }

    // 读取当前存储的locale
    fun getCurrentLocale(): String {
        return preferences.getString(KEY_LOCALE, "zh-CN") ?: "zh-CN"
    }
}

在Activity/Fragment中直接初始化即可,不需要手动传参:

val viewModel = ViewModelProvider(this)[LocaleViewModel::class.java]

方案2:依赖注入注入SharedPreferences实例(更规范,适合中大型项目)

如果项目使用Hilt、Dagger等依赖注入框架,可以直接将SharedPreferences实例注入到ViewModel中,完全解耦Context逻辑,可维护性更高。

第一步:提供SharedPreferences全局依赖(Hilt示例)

import android.content.Context
import android.content.SharedPreferences
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
class AppModule {
    companion object {
        private const val PREFERENCES_NAME = "app_config"
    }

    @Provides
    @Singleton
    fun provideSharedPreferences(@ApplicationContext context: Context): SharedPreferences {
        return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
    }
}

第二步:ViewModel中直接注入使用

import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject

@HiltViewModel
class LocaleViewModel @Inject constructor(
    private val preferences: SharedPreferences
) : ViewModel() {
    fun getCurrentLocale(): String {
        return preferences.getString("current_locale", "zh-CN") ?: "zh-CN"
    }
}

动态更新数据补充方案

如果需要locale变更时ViewModel的数据自动刷新,可以监听SharedPreferences的变更事件,同步更新状态:

import android.content.SharedPreferences
import androidx.lifecycle.MutableStateFlow
import androidx.lifecycle.ViewModel

@HiltViewModel
class LocaleViewModel @Inject constructor(
    private val preferences: SharedPreferences
) : ViewModel() {
    companion object {
        private const val KEY_LOCALE = "current_locale"
    }
    // 对外暴露的可观察locale状态
    val currentLocale = MutableStateFlow("zh-CN")

    // 监听配置变化
    private val preferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
        if (key == KEY_LOCALE) {
            currentLocale.value = preferences.getString(KEY_LOCALE, "zh-CN") ?: "zh-CN"
        }
    }

    init {
        preferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener)
    }

    override fun onCleared() {
        super.onCleared()
        // 页面销毁时解绑监听器避免泄漏
        preferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
    }
}

内容的提问来源于stack exchange,提问作者sooyeon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 19:36:04