SharedPreferences → DataStore
老写法(Java + SharedPreferences)
java
// 写入
SharedPreferences prefs = getSharedPreferences("settings", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("token", "abc123");
editor.putInt("userId", 42);
editor.putBoolean("isLogin", true);
editor.apply();
// 读取
String token = prefs.getString("token", "");
int userId = prefs.getInt("userId", 0);
boolean isLogin = prefs.getBoolean("isLogin", false);
问题在哪里
apply() 是异步写入但无返回值,写没写成功不知道。主线程读取 getString 可能触发磁盘 IO,卡 UI。不支持存储非基本类型,存个对象要先 JSON 序列化。多进程场景下数据不可靠。
新写法(Preferences DataStore)
添加依赖:
groovy
implementation "androidx.datastore:datastore-preferences:1.0.0"
定义 Key:
kotlin
object SettingsKeys {
val TOKEN = stringPreferencesKey("token")
val USER_ID = intPreferencesKey("userId")
val IS_LOGIN = booleanPreferencesKey("isLogin")
}
DataStore 实例:
kotlin
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")
读写:
kotlin
// 写入
viewModelScope.launch {
context.dataStore.edit { preferences ->
preferences[SettingsKeys.TOKEN] = "abc123"
preferences[SettingsKeys.USER_ID] = 42
preferences[SettingsKeys.IS_LOGIN] = true
}
}
// 读取 --- Flow
viewModelScope.launch {
context.dataStore.data.collect { preferences ->
val token = preferences[SettingsKeys.TOKEN] ?: ""
val userId = preferences[SettingsKeys.USER_ID] ?: 0
val isLogin = preferences[SettingsKeys.IS_LOGIN] ?: false
}
}
// 读取 --- 一次性
viewModelScope.launch {
val preferences = context.dataStore.data.first()
val token = preferences[SettingsKeys.TOKEN] ?: ""
}
一句话注意
DataStore 底层用 Protocol Buffers 序列化,数据存在 files/datastore/ 目录下,不是 XML。所有读写都用协程/Flow 完成,天然异步且主线程安全。
edit {} 的参数 preferences 是 MutablePreferences,和 Map 用法一样直接用 [] 赋值。同一个 edit {} 块内可以写多个 Key,会作为一个事务原子写入。
preferencesDataStore 委托属性是单例,同一个文件只能创建一个实例,多次调用返回同一个。在 Application 或顶层创建一次即可,不要在每个 Activity 里重复创建。
Java Android 老项目迁移系列,持续更新中。