SharedPreferences 详解
概述
SharedPreferences 是 Android 提供的轻量级数据存储机制,用于保存应用的配置信息和用户偏好设置。它以键值对的形式将数据存储在 XML 文件中(类似前端中的localStorage)。
核心特点
- 轻量级:适合存储少量简单数据
- 持久化:数据在应用重启后依然存在
- 线程安全:支持多线程访问
- 键值对存储:以 key-value 形式组织数据
基本用法
1. 初始化 SharedPreferences
// 获取 SharedPreferences 实例
SharedPreferences sharedPreferences = getSharedPreferences("文件名", MODE_PRIVATE);
参数说明:
文件名:XML文件名称,如 "MyPrefs" 会创建 MyPrefs.xmlMODE_PRIVATE:访问模式,只允许当前应用访问(推荐)
2. 保存数据
// 获取编辑器
SharedPreferences.Editor editor = sharedPreferences.edit();
// 只能保存六种类型的数据
editor.putString("username", "张三");
editor.putInt("age", 25);
editor.putBoolean("isLogin", true);
editor.putFloat("score", 98.5f);
editor.putLong("timestamp", System.currentTimeMillis());
Set<String> hobbies = new HashSet<>();
hobbies.add("游泳");
hobbies.add("跑步");
editor.putStringSet("hobbies", hobbies);
// 提交保存
editor.apply(); // 推荐:异步保存
// 或者
editor.commit(); // 同步保存,返回 boolean 结果
3. 读取数据
// 读取数据,提供默认值
String username = sharedPreferences.getString("username", "未知用户");
int age = sharedPreferences.getInt("age", 0);
boolean isLogin = sharedPreferences.getBoolean("isLogin", false);
float score = sharedPreferences.getFloat("score", 0.0f);
long timestamp = sharedPreferences.getLong("timestamp", 0L);
4. 删除数据
SharedPreferences.Editor editor = sharedPreferences.edit();
// 删除指定键
editor.remove("username");
// 清空所有数据
editor.clear();
// 提交删除操作
editor.apply();
每次修改(增加、删除)数据都需要多执行一次apply或者commit
支持的数据类型
| 方法 | 数据类型 | 示例 |
|---|---|---|
putString() / getString() | String | "Hello World" |
putInt() / getInt() | int | 123 |
putBoolean() / getBoolean() | boolean | true / false |
putFloat() / getFloat() | float | 3.14f |
putLong() / getLong() | long | 123456789L |
putStringSet() / getStringSet() | Set | {"item1", "item2"} |
apply() vs commit() 对比
| 特性 | apply() | commit() |
|---|---|---|
| 执行方式 | 异步 | 同步 |
| 返回值 | void | boolean |
| 性能 | 更好 | 较差 |
| UI阻塞 | 不会阻塞 | 可能阻塞 |
| 推荐使用 | ✅ 推荐 | ❌ 不推荐 |
// 推荐写法
editor.putString("key", "value");
editor.apply();
// 不推荐写法(除非需要返回结果)
boolean success = editor.putString("key", "value").commit();
实际应用场景
1. 用户偏好设置
// 保存主题设置
editor.putString("theme", "dark");
editor.putBoolean("notifications_enabled", true);
editor.apply();
// 读取设置
String theme = prefs.getString("theme", "light");
boolean notificationsEnabled = prefs.getBoolean("notifications_enabled", true);
2. 登录状态管理
// 保存登录信息
editor.putBoolean("is_logged_in", true);
editor.putString("user_token", "abc123");
editor.putLong("login_time", System.currentTimeMillis());
editor.apply();
// 检查登录状态
boolean isLoggedIn = prefs.getBoolean("is_logged_in", false);
3. 应用配置
// 首次启动标记
editor.putBoolean("first_launch", false);
editor.putInt("app_version", BuildConfig.VERSION_CODE);
editor.apply();
// 检查是否首次启动
boolean isFirstLaunch = prefs.getBoolean("first_launch", true);
文件存储位置
SharedPreferences 文件存储在应用的私有目录:
/data/data/包名/shared_prefs/文件名.xml
例如:
/data/data/com.example.myapp/shared_prefs/MyPrefs.xml
XML 文件格式示例
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="username">张三</string>
<int name="age" value="25" />
<boolean name="isLogin" value="true" />
<float name="score" value="98.5" />
<long name="timestamp" value="1234567890" />
</map>
使用范围和限制
✅ 适用场景
- 用户偏好设置(主题、语言等)
- 登录状态和用户信息
- 应用配置参数
- 简单的统计数据
- 首次启动标记
❌ 不适用场景
- 大量数据存储
- 复杂的数据结构
- 需要查询的数据
- 敏感信息(密码等)
- 频繁变化的数据
数据大小限制
- 建议单个文件不超过 1MB
- 适合存储少量配置数据
- 大量数据应使用 SQLite 数据库
与其他存储方式对比
| 存储方式 | 适用场景 | 数据大小 | 复杂度 | 查询能力 |
|---|---|---|---|---|
| SharedPreferences | 配置、偏好 | 小 | 简单 | 无 |
| SQLite | 结构化数据 | 大 | 中等 | 强 |
| 文件存储 | 任意数据 | 大 | 中等 | 无 |
| Room | 现代数据库 | 大 | 简单 | 强 |
最佳实践
1. 合理命名
// 好的命名
SharedPreferences userPrefs = getSharedPreferences("UserPreferences", MODE_PRIVATE);
SharedPreferences appSettings = getSharedPreferences("AppSettings", MODE_PRIVATE);
// 避免通用名称
SharedPreferences prefs = getSharedPreferences("data", MODE_PRIVATE);
2. 使用常量管理键名
public class PrefsKeys {
public static final String USER_NAME = "user_name";
public static final String IS_LOGGED_IN = "is_logged_in";
public static final String THEME = "theme";
}
// 使用常量
editor.putString(PrefsKeys.USER_NAME, username);
String userName = prefs.getString(PrefsKeys.USER_NAME, "");
3. 封装工具类
public class PrefsManager {
private static final String PREF_NAME = "MyAppPrefs";
private SharedPreferences prefs;
private SharedPreferences.Editor editor;
public PrefsManager(Context context) {
prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
editor = prefs.edit();
}
public void saveUserName(String userName) {
editor.putString("user_name", userName);
editor.apply();
}
public String getUserName() {
return prefs.getString("user_name", "");
}
}
注意事项
- 线程安全:SharedPreferences 是线程安全的,但 Editor 不是
- 内存占用:首次访问时会将整个文件加载到内存
- 性能考虑:避免在主线程进行大量读写操作
- 数据备份:SharedPreferences 会自动参与应用数据备份