SharedPreferences #
一、SharedPreferences概述 #
SharedPreferences是Android提供的一种轻量级数据存储方式,用于存储少量的键值对数据。它使用XML文件存储数据,适合存储简单的配置信息、用户偏好设置等。
1.1 特点 #
- 轻量级:适合存储少量数据
- 键值对:以键值对形式存储
- 持久化:数据保存在文件中
- 简单易用:API简单直观
1.2 适用场景 #
- 用户偏好设置
- 应用配置信息
- 简单的用户数据
- 登录状态保存
1.3 不适用场景 #
- 大量数据存储
- 复杂的数据结构
- 频繁的读写操作
- 需要事务支持的场景
二、基本使用 #
2.1 获取SharedPreferences #
kotlin
// 方式1:通过Context获取
val sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
// 方式2:通过Activity获取(文件名为当前Activity类名)
val sharedPreferences = getPreferences(Context.MODE_PRIVATE)
// 方式3:通过PreferenceManager获取(已废弃)
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
2.2 存储数据 #
kotlin
val sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
// 存储各种类型的数据
editor.putString("name", "张三")
editor.putInt("age", 25)
editor.putBoolean("isLogin", true)
editor.putFloat("score", 95.5f)
editor.putLong("timestamp", System.currentTimeMillis())
editor.putStringSet("tags", setOf("Android", "Kotlin"))
// 提交更改
editor.apply() // 异步提交
// 或
editor.commit() // 同步提交,返回是否成功
2.3 读取数据 #
kotlin
val sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
// 读取数据,提供默认值
val name = sharedPreferences.getString("name", "")
val age = sharedPreferences.getInt("age", 0)
val isLogin = sharedPreferences.getBoolean("isLogin", false)
val score = sharedPreferences.getFloat("score", 0f)
val timestamp = sharedPreferences.getLong("timestamp", 0L)
val tags = sharedPreferences.getStringSet("tags", emptySet())
2.4 删除数据 #
kotlin
val editor = sharedPreferences.edit()
// 删除指定键
editor.remove("name")
// 清空所有数据
editor.clear()
editor.apply()
2.5 检查键是否存在 #
kotlin
val containsName = sharedPreferences.contains("name")
// 获取所有键值对
val allEntries = sharedPreferences.all
三、apply vs commit #
| 特性 | apply() | commit() |
|---|---|---|
| 执行方式 | 异步 | 同步 |
| 返回值 | 无 | Boolean |
| 性能 | 较好 | 较差 |
| 使用场景 | 大多数情况 | 需要确认是否成功 |
kotlin
// 推荐:异步提交
editor.apply()
// 需要确认是否成功时使用
val success = editor.commit()
if (success) {
// 保存成功
} else {
// 保存失败
}
四、封装工具类 #
kotlin
object SPUtils {
private const val FILE_NAME = "app_prefs"
private lateinit var sharedPreferences: SharedPreferences
fun init(context: Context) {
sharedPreferences = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE)
}
fun put(key: String, value: Any?) {
val editor = sharedPreferences.edit()
when (value) {
is String -> editor.putString(key, value)
is Int -> editor.putInt(key, value)
is Boolean -> editor.putBoolean(key, value)
is Float -> editor.putFloat(key, value)
is Long -> editor.putLong(key, value)
is Set<*> -> editor.putStringSet(key, value as Set<String>)
}
editor.apply()
}
fun getString(key: String, defaultValue: String = ""): String {
return sharedPreferences.getString(key, defaultValue) ?: defaultValue
}
fun getInt(key: String, defaultValue: Int = 0): Int {
return sharedPreferences.getInt(key, defaultValue)
}
fun getBoolean(key: String, defaultValue: Boolean = false): Boolean {
return sharedPreferences.getBoolean(key, defaultValue)
}
fun getFloat(key: String, defaultValue: Float = 0f): Float {
return sharedPreferences.getFloat(key, defaultValue)
}
fun getLong(key: String, defaultValue: Long = 0L): Long {
return sharedPreferences.getLong(key, defaultValue)
}
fun remove(key: String) {
sharedPreferences.edit().remove(key).apply()
}
fun clear() {
sharedPreferences.edit().clear().apply()
}
fun contains(key: String): Boolean {
return sharedPreferences.contains(key)
}
}
五、监听数据变化 #
kotlin
class MainActivity : AppCompatActivity() {
private val listener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
when (key) {
"name" -> {
val newName = sharedPreferences.getString(key, "")
Log.d("SP", "Name changed to: $newName")
}
"isLogin" -> {
val isLogin = sharedPreferences.getBoolean(key, false)
Log.d("SP", "Login status: $isLogin")
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
sharedPreferences.registerOnSharedPreferenceChangeListener(listener)
}
override fun onDestroy() {
super.onDestroy()
val sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener)
}
}
六、存储复杂对象 #
6.1 使用JSON #
kotlin
// 存储对象
fun putObject(key: String, obj: Any) {
val json = Gson().toJson(obj)
sharedPreferences.edit().putString(key, json).apply()
}
// 读取对象
inline fun <reified T> getObject(key: String): T? {
val json = sharedPreferences.getString(key, null) ?: return null
return Gson().fromJson(json, T::class.java)
}
// 使用
data class User(val id: Int, val name: String)
val user = User(1, "张三")
putObject("user", user)
val savedUser: User? = getObject<User>("user")
6.2 使用序列化 #
kotlin
fun putSerializable(key: String, obj: Serializable) {
val baos = ByteArrayOutputStream()
val oos = ObjectOutputStream(baos)
oos.writeObject(obj)
val base64 = Base64.encodeToString(baos.toByteArray(), Base64.DEFAULT)
sharedPreferences.edit().putString(key, base64).apply()
}
@Suppress("UNCHECKED_CAST")
fun <T : Serializable> getSerializable(key: String): T? {
val base64 = sharedPreferences.getString(key, null) ?: return null
val bytes = Base64.decode(base64, Base64.DEFAULT)
val bais = ByteArrayInputStream(bytes)
val ois = ObjectInputStream(bais)
return ois.readObject() as T
}
七、多进程支持 #
7.1 MODE_MULTI_PROCESS(已废弃) #
kotlin
// 已废弃,不推荐使用
val sharedPreferences = getSharedPreferences("my_prefs", Context.MODE_MULTI_PROCESS)
7.2 使用ContentProvider #
对于多进程数据共享,推荐使用ContentProvider或其他IPC机制。
八、最佳实践 #
8.1 使用常量管理键名 #
kotlin
object SPKeys {
const val USER_NAME = "user_name"
const val USER_AGE = "user_age"
const val IS_LOGIN = "is_login"
const val THEME_MODE = "theme_mode"
}
// 使用
SPUtils.put(SPKeys.USER_NAME, "张三")
val name = SPUtils.getString(SPKeys.USER_NAME)
8.2 避免存储敏感数据 #
kotlin
// 错误:存储敏感数据
editor.putString("password", "123456")
editor.putString("token", "xxx")
// 正确:使用EncryptedSharedPreferences
val masterKey = MasterKey.Builder(context)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build()
val sharedPreferences = EncryptedSharedPreferences.create(
context,
"secret_prefs",
masterKey,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
8.3 避免频繁写入 #
kotlin
// 错误:频繁写入
for (i in 0..100) {
editor.putInt("key_$i", i).apply()
}
// 正确:批量写入
for (i in 0..100) {
editor.putInt("key_$i", i)
}
editor.apply()
8.4 使用DataStore替代 #
对于新项目,推荐使用Jetpack DataStore:
kotlin
// 添加依赖
dependencies {
implementation("androidx.datastore:datastore-preferences:1.0.0")
}
// 创建DataStore
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
// 存储数据
val KEY_NAME = stringPreferencesKey("name")
val KEY_AGE = intPreferencesKey("age")
scope.launch {
dataStore.edit { preferences ->
preferences[KEY_NAME] = "张三"
preferences[KEY_AGE] = 25
}
}
// 读取数据
val nameFlow: Flow<String> = dataStore.data.map { preferences ->
preferences[KEY_NAME] ?: ""
}
九、总结 #
本章详细介绍了SharedPreferences:
- SharedPreferences的基本概念和特点
- 数据的增删改查操作
- apply与commit的区别
- 工具类封装
- 监听数据变化
- 存储复杂对象
- 最佳实践
SharedPreferences适合存储简单的配置数据,对于复杂数据或大量数据,应考虑使用数据库或其他存储方式。
最后更新:2026-03-26