如何在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
相关产品推荐
相关产品推荐

