Объяснение Jetpack DataStore в Android

Объяснение Jetpack DataStore в Android

24 мая 2022 г.

Что такое хранилище данных?


Jetpack DataStore — это решение для хранения данных, которое позволяет хранить пары ключ/значение или буферы протоколов для хранения типизированных объектов. DataStore построен на сопрограммах Kotlin и Flow, поэтому все транзакции асинхронны, операции хранения и извлечения данных безопасны и производительны. Он заменит SharedPreferences.


Jetpack DataStore доступен в двух типах:


  • Preferences DataStore — хранит и извлекает данные с помощью ключей.

Не обеспечивает безопасность типов


  • Proto DataStore — хранит данные как экземпляры пользовательского типа данных.

Обеспечивает безопасность типов с помощью Protobuffers.


Для большинства приложений Preferences DataStore достаточно. Объекты Person обычно хранятся в базе данных комнаты.


Хранилище данных настроек


Реализация Preferences DataStore


Добавьте зависимости в файл build.gradle для вашего приложения или модуля:


```javascript


// Хранилище данных настроек (SharedPreferences, такие как API)


зависимости {


реализация ("androidx.datastore: datastore-preferences: 1.0.0")


Создание хранилища данных настроек


Создает делегат свойства для хранилища данных одного процесса. Это следует вызывать только один раз в файле (на верхнем уровне), и все использования DataStore должны использовать ссылку на один и тот же экземпляр. Тип получателя для делегата свойства должен быть экземпляром Context.


```java


val Context.dataStore: DataStore от предпочтенияDataStore(


имя = "настройки",


обработчик коррупции = ноль,


productMigrations = {контекст ->


пустой список()


scope = CoroutineScope(Dispatchers.IO + Job())


  • name - Имя настройки. Настройки будут храниться в файле в подкаталоге «datastore/» в каталоге файлов контекста приложения и генерируются с использованием preferencesDataStoreFile.

  • corporationHandler — повреждающий обработчик вызывается, если хранилище данных сталкивается с исключением.

  • productMigrations - производить миграции. ApplicationContext передается этим обратным вызовам в качестве параметра. DataMigrations запускаются до того, как может произойти какой-либо доступ к данным.

  • scope — область, в которой будут выполняться операции ввода-вывода и функции преобразования.

Создание ключей


Давайте создадим объекты, содержащие ключи, которые мы будем использовать


```java


сопутствующий объект {


val IS_DARK_MODE = booleanPreferencesKey("dark_mode")


Чтение из Proto DataStore


Для доступа к данным используйте DataStore.data. Добавьте блок catch для обработки ошибок.


DataStore предоставляет сохраненные данные в объекте Preferences.


```javascript


перечисляемый класс UiMode {


СВЕТЛЫЙ ТЕМНЫЙ


val uiModeFlow: Flow = context.dataStore.data


.ловить {


если (это IOException) {


it.printStackTrace()


испускать (пустые настройки ())


} еще {


брось это


.map { предпочтение ->


// Нет безопасности типов.


когда (предпочтение [IS_DARK_MODE] ?: ложь) {


правда -> UiMode.DARK


ложь -> UiMode.LIGHT


Запись в хранилище данных настроек


Preferences DataStore предоставляет функцию edit(), которая транзакционно обновляет данные в DataStore. DataStore.edit() — это функция приостановки и расширения хранилища данных. Все операции безопасны и сериализованы. Сопрограмма завершится, когда данные будут надежно сохранены на диске.


```javascript


приостановить веселье setUiMode (uiMode: UiMode) {


context.dataStore.edit { настройки ->


предпочтения[IS_DARK_MODE] = когда (uiMode) {


UiMode.LIGHT -> ложь


UiMode.DARK -> правда


Буферы протокола


Реализация Proto DataStore


Добавьте зависимости в файл build.gradle для вашего приложения или модуля:


```javascript


плагины {


идентификатор "com.google.protobuf", версия "0.8.18"


зависимости {


//Хранилище данных


реализация "androidx.datastore:datastore:1.0.0"


// Вам нужно полагаться на библиотеку времени выполнения lite, а не на protobuf-java


реализация 'com.google.protobuf:protobuf-javalite:3.20.1'


протобаф {


протокол {


артефакт = 'com.google.protobuf:протокол:3.20.1'


генерироватьProtoTasks {


все (). каждая { задача ->


задача.встроенные {


Джава {


вариант «облегченный»


Ознакомьтесь с плагином Protobuf для заметок Gradle


Синхронизируйте проект, чтобы сгенерировать java-класс для DataStore по схеме из proto.


Определение схемы


Реализация Proto DataStore использует DataStore и протокольные буферы для сохранения типизированных объектов на диске. Чтобы узнать больше об определении схемы proto, см. руководство по языку protobuf.


Для описания схемы настроек необходимо создать файл proto в папке app/src/main/proto/, файл с расширением *.proto


Эта схема определяет тип объектов, которые должны сохраняться в Proto DataStore.


```javascript


синтаксис = "прото3";


option java_package = "com.example.protodatastore";


опция java_multiple_files = истина;


сообщение Человек {


идентификатор int32 = 1;


строка first_name = 2;


строка last_name= 3;


  • syntax — указывает, что вы используете синтаксис proto3

  • java_package - указывает, куда вы хотите, чтобы компилятор поместил сгенерированные файлы.

  • java_multiple_files – установленное значение true означает, что генератор кода будет создавать отдельный файл для каждого сообщения верхнего уровня.

  • message - ключевое слово для определения структуры

  • Маркеры 1, 2, 3 идентифицируют уникальный тег, который поле использует в двоичном кодировании.

Полезный плагин для протофайлов - Редактор буфера протокола.


Создание сериализатора


Сериализатор возьмет поток байтов и создаст экземпляр Person как поток байтов.


разобрать.


Этот объект Serializer должен быть создан как синглтон


```javascript


объект PersonSerializer : Serializer {


переопределить приостановку удовольствия readFrom(input: InputStream): Person {


пытаться {


вернуть Person.parseFrom (ввод)


} поймать (исключение: InvalidProtocolBufferException) {


бросить CorruptionException("CorruptionException proto", исключение)


переопределить приостановку удовольствия writeTo(t: Person, output: OutputStream) = t.writeTo(output)


переопределить val defaultValue: Person = Person.getDefaultInstance()


  • defaultValue — возвращает значение по умолчанию, если ничего не найдено

  • writeTo – как конвертировать в формат хранения

  • readFrom - обратное преобразование формата хранения

Создание прототипа хранилища данных


Создайте экземпляр Proto DataStore с помощью createDataStore()


```java


private val Context.dataStore: DataStore = context.createDataStore(


имя_файла = "*.прото" ,


сериализатор = PersonSerializer ,


Используйте fileName файла, в котором вы будете сохранять данные.


Используйте сериализатор, который мы создали ранее.


Чтение


Получите объект данных: Flow, который вернет нам


фактический экземпляр модели, хранящийся в DataStore:


```javascript


val personFlow: Flow = dataStore.data


Не накладывайте кеш поверх этого API: будет невозможно гарантировать согласованность. Вместо этого используйте data.first() для доступа к одному снимку.


Письмо


Используйте метод приостановки DataStore.updateData() для транзакционного обновления данных в атомарной операции чтения-изменения-записи. Все операции сериализованы, а само преобразование — это сопрограмма.


```javascript


приостановить удовольствие updateIsRegistered(firstName: String) {


dataStore.updateData {personSettings ->


person.toBuilder().setFirstName(firstName).build()


  • toBuilder() – получает версию Builder нашего человека

  • .setFirstName(firstName) — устанавливает новое значение

  • .build() – обновление путем преобразования в `PersonPreferences

Вывод


DataStore — это замена SharedPreferences, которая устраняет большинство недостатков синхронного API, отсутствие механизма сигнализации ошибок, отсутствие транзакционного API и другие. DataStore дает нам очень простой и удобный инструмент. Если вам нужны частичные обновления, ссылочная целостность или поддержка больших данных, рассмотрите возможность использования Room API вместо DataStore. Хранилище данных используется для небольших простых наборов данных, таких как параметры приложения и состояние. Он не поддерживает частичные обновления: при изменении любого поля весь объект будет сериализован и сохранен на диск.



Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE