Android DataStore:安全存储和轻松管理数据

简介: Android DataStore:安全存储和轻松管理数据
关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

在这里插入图片描述

一、导读

我们继续总结学习Java基础知识,温故知新。

二、概览

DataStore 是一种用于 Android 应用程序数据存储的新的推荐方式。
它是在 Android Jetpack 组件中引入的,旨在替代 SharedPreferences,并提供更强大、易于使用的 API。

DataStore 基于 Kotlin 协程和 Flow 构建而成, 提供了一种类型安全且异步的数据存储解决方案。
相比于 SharedPreferences,DataStore 具有以下优点:

  1. 异步操作:DataStore 提供了异步的读写操作,避免了阻塞主线程的问题。这使得在读取和写入数据时,应用程序可以更好地保持响应性能。
  2. 类型安全:DataStore 支持使用协议缓冲区(Protocol Buffers)来定义数据模型,这样可以确保在编译时进行类型检查。数据模型的更改不会导致运行时错误,而是在编译时进行检测。
  3. 支持多种数据类型:DataStore 支持存储不同类型的数据,包括原始类型、对象或自定义类。
  4. 数据一致性:DataStore 提供了一致性和安全性保证,保证在多个写入操作中的数据一致性。
  5. 流式数据访问:DataStore 支持使用流(Flow)来访问数据,使得可以轻松地观察数据的变化并进行相应的更新。

DataStore 提供了两个主要的实现方式:PreferencesDataStore 和 ProtoDataStore。
PreferencesDataStore 适用于存储简单的数据类型,使用键值对来存储数据。
ProtoDataStore 则使用 Protocol Buffers 定义数据模型,并支持存储更复杂的数据结构(类型化对象)。

三、使用

3.1 Preferences DataStore

适用于存储简单的数据类型,使用键值对来存储数据

添加依赖

    // Preferences DataStore (SharedPreferences like APIs)
    dependencies {
        implementation "androidx.datastore:datastore-preferences:1.0.0"

        // optional - RxJava2 support
        implementation "androidx.datastore:datastore-preferences-rxjava2:1.0.0"

        // optional - RxJava3 support
        implementation "androidx.datastore:datastore-preferences-rxjava3:1.0.0"
    }

    // Alternatively - use the following artifact without an Android dependency.
    dependencies {
        implementation "androidx.datastore:datastore-preferences-core:1.0.0"
    }
    

数据读写

RxDataStore<Preferences> dataStore =
  new RxPreferenceDataStoreBuilder(context, /*name=*/ "settings").build();

Preferences.Key<Integer> EXAMPLE_COUNTER = PreferencesKeys.int("example_counter");

Flowable<Integer> exampleCounterFlow = dataStore.data().map(prefs -> prefs.get(EXAMPLE_COUNTER));

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);
});
// The update is completed once updateResult is completed.

3.2 ProtoDataStore

使用 Protocol Buffers 定义数据模型,并支持存储更复杂的数据结构

添加依赖

    // Typed DataStore (Typed API surface, such as Proto)
    dependencies {
        implementation "androidx.datastore:datastore:1.0.0"

        // optional - RxJava2 support
        implementation "androidx.datastore:datastore-rxjava2:1.0.0"

        // optional - RxJava3 support
        implementation "androidx.datastore:datastore-rxjava3:1.0.0"
    }

    // Alternatively - use the following artifact without an Android dependency.
    dependencies {
        implementation "androidx.datastore:datastore-core:1.0.0"
    }
    

数据读写

Proto DataStore 要求在 app/src/main/proto/ 目录的 proto 文件中保存预定义的架构。
此架构用于定义在 Proto DataStore 中保存的对象的类型。

syntax = "proto3";

option java_package = "com.example.application";
option java_multiple_files = true;

message Settings {
  int32 example_counter = 1;
}
private static class SettingsSerializer implements Serializer<Settings> {
  @Override
  public Settings getDefaultValue() {
    Settings.getDefaultInstance();
  }

  @Override
  public Settings readFrom(@NotNull InputStream input) {
    try {
      return Settings.parseFrom(input);
    } catch (exception: InvalidProtocolBufferException) {
      throw CorruptionException(“Cannot read proto.”, exception);
    }
  }

  @Override
  public void writeTo(Settings t, @NotNull OutputStream output) {
    t.writeTo(output);
  }
}

RxDataStore<Byte> dataStore =
    new RxDataStoreBuilder<Byte>(context, /* fileName= */ "settings.pb", new SettingsSerializer()).build();



Flowable<Integer> exampleCounterFlow =
        dataStore.data().map(settings -> settings.getExampleCounter());

Single<Settings> updateResult = dataStore.updateDataAsync(currentSettings ->
                Single.just(
                        currentSettings.toBuilder()
                                .setExampleCounter(currentSettings.getExampleCounter() + 1)
                                .build()));    

3.3、在同步代码中使用 DataStore

DataStore 的主要优势之一是异步 API,但可能不一定始终能将周围的代码更改为异步代码。如果您使用的现有代码库采用同步磁盘 I/O,或者您的依赖项不提供异步 API,就可能出现这种情况。

Kotlin 协程提供 runBlocking() 协程构建器,以帮助消除同步与异步代码之间的差异。您可以使用 runBlocking() 从 DataStore 同步读取数据。RxJava 在 Flowable 上提供阻塞方法。以下代码会阻塞发起调用的线程,直到 DataStore 返回数据:

Settings settings = dataStore.data().blockingFirst();

dataStore.data().first().subscribe();
这样,DataStore 可以异步读取数据并将其缓存在内存中。以后使用 runBlocking() 进行同步读取的速度可能会更快,或者如果初始读取已经完成,可能也可以完全避免磁盘 I/O 操作。
  • 请尽可能避免在 DataStore 数据读取时阻塞线程。阻塞界面线程可能会导致 ANR 或界面卡顿,而阻塞其他线程可能会导致死锁。

3.4、在多进程代码中使用 DataStore

  • DataStore 多进程功能目前仅在 1.1.0 Alpha 版中提供

为了能够在不同进程中使用 DataStore,需要使用 MultiProcessDataStoreFactory 构造 DataStore 对象。

val dataStore: DataStore<Settings> = MultiProcessDataStoreFactory.create(
   serializer = SettingsSerializer(),
   produceFile = {
       File("${context.cacheDir.path}/myapp.preferences_pb")
   }
)

四、DataStore & MMKV

看一组数据对比,图片来源于MMKV 开源网站
在这里插入图片描述

在这里插入图片描述

至于如何使用就不描述了,非常简单。
个人感觉 DataStore 没有 MMKV 好用,推荐使用 MMKV,但是各有优劣吧。

jetpack 官网
datastore

五、 推荐阅读

Java 专栏

[SQL 专栏]
[数据结构与算法]
[Android学习专栏]

相关文章
|
存储 安全 API
Android经典实战之存储方案对比:SharedPreferences vs MMKV vs DataStore
本文介绍了 Android 开发中常用的键值对存储方案,包括 SharedPreferences、MMKV 和 DataStore,并对比了它们在性能、并发处理、易用性和稳定性上的特点。通过实际代码示例,帮助开发者根据项目需求选择最适合的存储方案,提升应用性能和用户体验。
1407 1
|
存储 安全 Java
一文带你玩转 DataStore
一文带你玩转 DataStore
959 0
一文带你玩转 DataStore
|
存储 Android开发 C++
【Android 从入门到出门】第五章:使用DataStore存储数据和测试
【Android 从入门到出门】第五章:使用DataStore存储数据和测试
604 3
|
Android开发
android hilt使用详解
android hilt使用详解
1047 0
|
缓存 API Android开发
Android Kotlin之Flow数据流
`Flow`是`google`官方提供的一套基于`kotlin`协程的响应式编程模型,它与`RxJava`的使用类似,但相比之下`Flow`使用起来更简单,另外`Flow`作用在协程内,可以与协程的生命周期绑定,当协程取消时,`Flow`也会被取消,避免了内存泄漏风险。
1988 1
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
1129 18
|
存储 XML 安全
Android Jetpack系列之DataStore
`Jetpack DataStore` 是一种改进的新数据存储解决方案,允许使用**协议缓冲区**存储键值对或类型化对象。`DataStore` **以异步、一致的事务方式存储数据,克服了 SharedPreferences(以下统称为SP)的一些缺点**。`DataStore`基于`Kotlin`协程和`Flow`实现,并且可以对`SP`数据进行迁移,旨在取代`SP`
981 0
|
存储 XML 前端开发
Android Jetpack系列之ViewModel
ViewModel的定义:**ViewModel旨在以注重生命周期的方式存储和管理界面相关的数据**。ViewModel本质上是视图(View)与数据(Model)之间的桥梁,想想以前的MVC模式,视图和数据都会写在Activity/Fragment中,导致Activity/Fragment过重,后续难以维护,而ViewModel将视图和数据进行了分离解耦,为视图层提供数据。
692 0
|
存储 安全 API
Jetpack之DataStore使用
前言DataStore提供了一种安全且持久的方式来存储少量数据。它不支持部分更新:如果任何字段被修改,整个对象将被序列化并持久到磁盘。它是线程安全的,非阻塞的。特别是,它解决了SharedPreferences这些设计缺陷:同步API鼓励违反StrictModeapply和commit没有发出错误信号的机制apply将阻塞fsync上的UI线程不持久-它可以返回尚未持久的状态没有一致性或事务语义在
650 0
Jetpack之DataStore使用
|
Java Android开发
三句代码创建全屏Dialog或者DialogFragment:带你从源码角度实现
三句代码创建全屏Dialog或者DialogFragment:带你从源码角度实现
1550 0
三句代码创建全屏Dialog或者DialogFragment:带你从源码角度实现

热门文章

最新文章