先来看看官网的介绍: Jetpack DataStore 是一种数据存储解决方案,允许您使用协议缓冲区存储键值对或类型化对象。DataStore 使用 Kotlin 协程和 Flow 以异步、一致的事务方式存储数据。
注意:如果您需要支持大型或复杂数据集、部分更新或参照完整性,请考虑使用 Room,而不是 DataStore。DataStore 非常适合简单的小型数据集,不支持部分更新或参照完整性。
DataStore 提供两种不同的实现:Preferences DataStore 和 Proto DataStore。
-
Preferences DataStore 使用键存储和访问数据。此实现不需要预定义的架构,也不确保类型安全。
-
Proto DataStore 将数据作为自定义数据类型的实例进行存储。此实现要求您使用协议缓冲区来定义架构,但可以确保类型安全。
DataStore 的优势
- 基于
Coroutine Flow实现 - 保证数据访问一致性
- 异常处理机制
- 异步访问,避免同步阻塞
- 基于
Protobuf,实现非基本型数据的存储
对比SharePreference
- SharedPreferences 有一个看上去可以在 UI 线程安全调用的同步 API,但是该 API 实际上执行了磁盘 I/O 操作。此外,apply() 方法会在 fsync() 阻塞 UI 线程。在您应用的任何地方,每当 Service 或 Activity 启动或停止时,就会触发等待 fsync() 的调用。由 apply() 安排的 fsync() 调用过程会阻塞 UI 线程,这也常常成为造成 ANR 的源头。
- SharedPreferences 在分析出错时会抛出运行时异常。
官方对比图:

使用 Preferences DataStore 存储键值对
依赖
// Typed DataStore (Typed API surface, such as Proto)
dependencies {
implementation "androidx.datastore:datastore:1.0.0-alpha08"
// optional - RxJava2 support
implementation "androidx.datastore:datastore-rxjava2:1.0.0-alpha08"
}
复制代码
Preferences DataStore 实现使用 DataStore 和 Preferences 类将简单的键值对保留在磁盘上。
创建 Preferences DataStore
使用由 preferencesDataStore 创建的属性委托来创建 Datastore<Preferences> 实例。在您的 Kotlin 文件顶层调用该实例一次,便可在应用的所有其余部分通过此属性访问该实例。这样可以更轻松地将 DataStore 保留为单例。此外,如果您使用的是 RxJava,请使用 RxPreferenceDataStoreBuilder。必需的 name 参数是 Preferences DataStore 的名称。
RxDataStore<Preferences> dataStore =
new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();
// 实践
// 文件中的 Key
Preferences.Key<String> USER_NAME = PreferencesKeys.stringKey("USER_NAME");
Preferences.Key<String> USER_PASSWD = PreferencesKeys.stringKey("USER_PASSWD");
// 创建 Preferences DataStore
// 可以在 files/datastore 目录下看到 USER_NAME.preferences_pd 文件
RxDataStore<Preferences> dataStore = new RxPreferenceDataStoreBuilder(mContext, "USER_NAME").build();
复制代码
从 Preferences DataStore 读取内容
由于 Preferences DataStore 不使用预定义的架构,因此您必须使用相应的键类型函数为需要存储在 DataStore<Preferences> 实例中的每个值定义一个键。例如,如需为 int 值定义一个键,请使用 intPreferencesKey()。然后,使用 DataStore.data 属性,通过 Flow 提供适当的存储值。
Preferences.Key<Integer> EXAMPLE_COUNTER = PreferencesKeys.int("example_counter");
Flowable<Integer> exampleCounterFlow =
dataStore.data().map(prefs -> prefs.get(EXAMPLE_COUNTER));
// 实践 -- 从文件中读取用户名和密码
// 读取 Preferences DataStore 数据 通过 get 方法
Flowable<String> userNameFlow =
dataStore.data().map(prefs -> prefs.get(USER_NAME));
Flowable<String> userPasswdFlow =
dataStore.data().map(prefs -> prefs.get(USER_PASSWD));
try {
// 填入文本框中
accountEditText.setText(userNameFlow.blockingFirst());
passwdEditText.setText(userPasswdFlow.blockingFirst());
}catch (RuntimeException e) {
e.printStackTrace();
}
复制代码
将内容写入 Preferences DataStore
Preferences DataStore 提供了一个 edit() 函数,用于以事务方式更新 DataStore 中的数据。该函数的 transform 参数接受代码块,您可以在其中根据需要更新值。转换块中的所有代码均被视为单个事务。
Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
Integer currentInt = prefsIn.get(INTEGER_KEY);
mutablePreferences.set(INTEGER_KEY, currentInt != null ? currentInt + 1 : 1);
return Single.just(mutablePreferences);
});
// 实践
// 写入数据 将用户名作为KEY
// VALUE 是一个String类型
Single<Preferences> updateResult = dataStore.updateDataAsync(prefsIn -> {
MutablePreferences mutablePreferences = prefsIn.toMutablePreferences();
// String userName = prefsIn.get(USER_NAME); // 该方法可以获取到该键的value
// 将键值对写入 key: USER_NAME | value: account
mutablePreferences.set(USER_NAME, account);
// 将键值对写入 key: USER_PASSWD | value: passwd
mutablePreferences.set(USER_PASSWD, passwd);
return Single.just(mutablePreferences);
});
复制代码



















![[02/27][官改] Simplicity@MIX2 ROM更新-一一网](https://www.proyy.com/wp-content/uploads/2020/02/3168457341.jpg)


![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)