Jetpack DataStore 你总要了解一下吧?

网友投稿 1058 2022-05-29

一、DataStore 介绍

DataStore 是 Android Jetpack 中的一个组件,它是一个数据存储的解决方案,跟 SharedPreferences 一样,采用key-value形式存储。DataStore 保证原子性,一致性,隔离性,持久性。尤其是,它解决了 SharedPreferences API 的设计缺陷。Jetpack DataStore 是经过改进的新版数据存储解决方案,旨在取代 SharedPreferences,让应用能够以异步、事务方式存储数据。

注意:DataStore 比较适合小数据和简单操作,并且无法局部的更新数据。如果你需要支持大型或复杂的数据集、部分更新或引用完整性,请考虑使用 Room 而不是 DataStore。

Preferences DataStore 和 Proto DataStore

Preferences DataStore:与SharedPreferences类似,通过键值对存储数据,此实现不需要预定义模式,也不提供类型安全。

Proto DataStore:通过Protocol-Buffers定义存储数据类型以及结构,保证类型安全。

一、DataStore 介绍

DataStore 是 Android Jetpack 中的一个组件,它是一个数据存储的解决方案,跟 SharedPreferences 一样,采用key-value形式存储。DataStore 保证原子性,一致性,隔离性,持久性。尤其是,它解决了 SharedPreferences API 的设计缺陷。Jetpack DataStore 是经过改进的新版数据存储解决方案,旨在取代 SharedPreferences,让应用能够以异步、事务方式存储数据。

注意:DataStore 比较适合小数据和简单操作,并且无法局部的更新数据。如果你需要支持大型或复杂的数据集、部分更新或引用完整性,请考虑使用 Room 而不是 DataStore。

Preferences DataStore 和 Proto DataStore

Preferences DataStore:与SharedPreferences类似,通过键值对存储数据,此实现不需要预定义模式,也不提供类型安全。

Proto DataStore:通过Protocol-Buffers定义存储数据类型以及结构,保证类型安全。

本文重点了解Preferences DataStore。

二、Preferences DataStore

与SharedPreferences类似,通过键值对存储数据,此实现不需要预定义模式,也不提供类型安全。

2.1 添加依赖

在你项目的app_module对应的build.gradle中添加如下依赖:

dependencies { //Typed DataStore (Typed API surface, such as Proto) implementation "androidx.datastore:datastore:1.0.0" // //可选 - RxJava2 support // implementation "androidx.datastore:datastore-rxjava2:1.0.0" // //可选 - RxJava3 support implementation "androidx.datastore:datastore-rxjava3:1.0.0" //Preferences DataStore (SharedPreferences like APIs) implementation "androidx.datastore:datastore-preferences:1.0.0" // // 可选 - RxJava2 support // implementation "androidx.datastore:datastore-preferences-rxjava2:1.0.0" // // 可选 - RxJava3 support implementation "androidx.datastore:datastore-preferences-rxjava3:1.0.0" }

2.2 使用 Preferences DataStore 存储键值对

首先看看 DataStore 源码,DataStore 是一个接口。

package androidx.datastore.core import kotlinx.coroutines.flow.Flow import java.io.IOException /** * DataStore数据存储提供了一种安全、持久的方式来存储少量数据,如 preferences 和应用程序状态。 * 数据存储提供了ACID保证。它是线程安全的,并且不阻塞。特别是,它解决了SharedReferences API的这些设计缺陷: * 1. Synchronous API encourages StrictMode violations * 2. apply() and commit() have no mechanism of signalling errors * 3. apply() will block the UI thread on fsync() * 4. Not durable – it can returns state that is not yet persisted * 5. No consistency or transactional semantics * 6. Throws runtime exception on parsing errors * 7. Exposes mutable references to its internal state */ public interface DataStore { public val data: Flow public suspend fun updateData(transform: suspend (t: T) -> T): T }

以上可以看出 DataStore 是基于 协程 和 Flow 实现的。

data 是一个 Flow 对象。

updateData() 用于更新对象。

并且查看 DataStore 的其他相关源码你会发现他们都是基于Kotlin语言开发。Google 对于推 Kotlin 那是相当执着。

2.2.1 创建 DataStore

使用 preferencesDataStore(Kotlin) 创建Datastore 的实例。

如果你使用 RxJava,要使用 RxPreferenceDataStoreBuilder。

必需的 name 参数是 Preferences DataStore 的名称。

这里我们使用的是RxJava:

RxDataStore dataStore = new RxPreferenceDataStoreBuilder(this, /*name=*/ "datastore_sc").build(); //创建使用的key Preferences.Key nameKey = PreferencesKeys.stringKey("name"); Preferences.Key ageKey = PreferencesKeys.intKey("age");

默认路径:/data/data/com.scc.datastorage/files/datastore/datastore_sc.preferences_pb

这里创建了两个key,分别是 String 类型和 Int 类型。

2.2.1 DataStore 写入数据

//关于 nameKey 和 ageKey 请看上面代码。 putString(nameKey, "name-Scc"); putInteger(ageKey, 25); //2022/1/25 功能:存入String类型的数据 private void putString(Preferences.Key nameKey, String value) { dataStore.updateDataAsync(new Function>() { @Override public Single apply(Preferences preferences) throws Throwable { MutablePreferences mutablePreferences = preferences.toMutablePreferences(); mutablePreferences.set(nameKey, value); return Single.just(mutablePreferences); } }); } //2022/1/25 功能:存入Integer类型的数据 private void putInteger(Preferences.Key ageKey, Integer value) { dataStore.updateDataAsync(new Function>() { @Override public Single apply(Preferences preferences) throws Throwable { MutablePreferences mutablePreferences = preferences.toMutablePreferences(); mutablePreferences.set(ageKey, value); return Single.just(mutablePreferences); } }); }

这里写入的两种类型,这样更加仿版理解和你写成自己的工具类,因为使用 DataStore 比较少实践少就不提供工具类了,以免误导大家。

2.2.3 DataStore 读取数据

getString(nameKey); getInteger(ageKey); //2022/1/25 功能:获取String类型数据 private void getString(Preferences.Key nameKey) { Log.e("DataStore", nameKey.toString()); Flowable example = dataStore.data().map(new Function() { @Override public String apply(Preferences preferences) { Log.e("DataStore.apply", preferences.get(nameKey)); return preferences.get(nameKey); } }); Log.e("DataStore.Flowable", example.first("default").blockingGet()); } //2022/1/25 功能:获取Integer类型数据 private void getInteger(Preferences.Key ageKey) { Log.e("DataStoreKey", ageKey.toString()); Flowable example = dataStore.data().map(new Function() { @Override public Integer apply(Preferences preferences) { Log.e("DataStore.apply", preferences.get(ageKey).intValue() + ""); return preferences.get(ageKey); } }); Log.e("DataStore.Flowable", example.first(12).blockingGet().toString()); }

三、Proto DataStore

通过Protocol-Buffers定义存储数据类型以及结构,保证类型安全。

Proto DataStore 实现使用 DataStore 和 Protocol-Buffers 将类型化对象持久保存到磁盘。

什么是 Protocol-Buffers?

Protocol-Buffers是谷歌的语言中立、平台中立、可扩展的机制,用于序列化结构化数据——比如XML,但更小、更快、更简单。您只需定义一次数据的结构化方式,然后就可以使用特殊生成的源代码,轻松地在各种数据流之间以及使用各种语言编写和读取结构化数据。

3.1 定义架构

Proto DataStore 需要app/src/main/proto/目录中的 proto 文件中的预定义模式。此架构定义了您在 Proto DataStore 中持久保存的对象的类型。

syntax = "proto3"; option java_multiple_files = true; option java_package = "com.scc.datastorage.proto"; option java_outer_classname = "User"; message User{ string name = 1; int32 age = 2; }

.proto 文件以包声明开头,这有助于防止不同项目之间的命名冲突。

java_multiple_files:可以为每个生成的类生成一个单独的 .java 文件。

Jetpack DataStore 你总要了解一下吧?

java_package:指定生成的类应该使用什么 Java 包名称。如果您没有明确指定,它只会匹配包声明给出的包名。

java_outer_classname:定义了类名。如果没有设置这个 options ,它将通过将文件名转换为大写驼峰式来生成。例如,默认情况下,“my_proto.proto”将使用“MyProto”作为包装类名称。

定义 message:

可以使用许多标准的简单数据类型可用作字段类型,包括 bool、int32、float、double 和 string。

可以使用许多标准的简单数据类型可用作字段类型,包括 bool、int32、float、double 和 string。

还可以通过使用其他 message 类型作为字段类型来为你的消息添加进一步的结构。

还可以通过使用其他 message 类型作为字段类型来为你的消息添加进一步的结构。

每个元素上的 "= 1"、"= 2" 标记标识该字段在二进制编码中使用的唯一 "tag"。

更多关于 的内容可以去官网找找 protobuf 语言指南。

注意:存储对象的类是在编译时从 proto 文件中定义的message生成的。确保你 rebuild 你的项目。

3.2 创建 Proto DataStore

1.定义一个实现 Serializer 的类,其中 T 是 proto 文件中定义的类型。

2.使用 dataStore 创建的属性委托来创建 DataStore 的实例,其中 T 是 proto 文件中定义的类型。

写到这里 proto 文件中定义的类无法生成,也尝试了很多办法,不知道什么情况。后续步骤可参照官网,其他方法和Preferences DataStore类似。就不占用篇幅了。

相关链接

官方文档 DataStore;

个人感觉 DataStore 还是没有 SP 和 MMKV 好用,推荐使用 MMKV 毕竟上线好几年了,而且是大厂推出,相对稳定一些,有些个人自己实现了 SP 的功能,但是万一有 Bug 或者突然不继续维护了是不是就尴尬了。

Android Java

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:看完这篇博客,Python Django 你就学会一半了
下一篇:【已开源】华为诺亚方舟实验室首创针对生成对抗网络(GAN)的剪枝算法
相关文章