Рекомендуемое Jetpack решение для хранения данных с использованием Protobufs, обеспечивающее безопасность типов.
Вступление
SharedPreferences - общий способ хранения пар ключ-значение в локальном хранилище. Datastore заменяет SharedPreferences, устраняя его недостатки. Datastore - это передовое решение для хранения данных, созданное с использованием сопрограмм Kotlin и Flow для хранения данных асинхронно, согласованно и транзакционно. Есть два способа хранить данные в DataStore. Это Preferences DataStore и Proto DataStore. Пожалуйста, ознакомьтесь с моим предыдущим постом о введении в Datastore и Preferences DataStore.
В этом посте мы узнаем больше о следующем:
- Proto DataStore
- Protobufs
- Базовая реализация Proto DataStore
Для понимания этого необходимо знакомство с сопрограммами и Kotlin Flow.
Если вы хотите перейти непосредственно к базе кода, загляните в репозиторий GitHub.
Что такое Proto DataStore?
Мы привыкли к системе пары ключ-значение для хранения данных в общих настройках и хранилище данных предпочтений. Однако Proto DataStore хранит данные как экземпляры настраиваемого типа данных, а не пар "ключ-значение". Proto DataStore нуждается в предопределенной схеме с типами данных и экземплярами, которые необходимо сохранить. Такой подход к схеме помогает обеспечить безопасность типов с помощью предопределенных типов данных. Нам нужно определить схему, используя буферы протокола.
- Сохраняет данные как экземпляры настраиваемого типа данных.
- Определяет схему с использованием буферов протокола. Использование Protobufs позволяет сохранять строго типизированные данные.
- Они быстрее, меньше, проще и менее неоднозначны, чем XML и другие подобные форматы данных.
Нам нужно использовать новый механизм сериализации для Proto DataStore, который мы увидим позже в этом посте. Прежде чем переходить к реализации, давайте немного узнаем о буферах протокола.
Что такое буферы протокола?
Буферы протокола, обычно называемые Protobufs, являются независимыми от языка и платформы механизмами сериализации данных. Protobufs лучше всего подходят для сценариев, где требуется более быстрая связь по сети или для хранения данных. Google создал формат ProtoBuf в 2008 году. Это альтернативное решение JSON и XML для максимально быстрой сериализации и десериализации данных.
Текущая версия Protobuf - proto3. Мы будем использовать эту версию proto3 позже для создания нашего хранилища данных proto. Важно знать механизм Protobufs. В этом механизме мы используем прото-файлы с .proto
расширениями, куда мы записываем данные для сериализации. Прототипы файлов содержат типы сообщений, в которых мы определяем наши данные.
Давайте создадим простой прототип файла с типом сообщения по сравнению с типом JSON для лучшего понимания. Более простой файл JSON будет выглядеть, как показано ниже.
{ is_logged_in: true, user_name: "Android" }
Теперь давайте создадим для этого формат файла proto
syntax = "proto3"; message UserData{ bool is_logged_in = 1; string user_name = 2; }
Для каждого поля нам нужно определить Field Types
, Field Numbers
, Field Rules
и т. Д. Чтобы узнать больше о Protobufs, ознакомьтесь с Руководством Google для Protobufs
Примечание: файлы прототипов могут быть скомпилированы для генерации кода в соответствии с языком программирования пользователя.
Хватит разговоров, перейдем к кодированию ...
Выполнение
Давайте создадим UserDataStore, где мы будем хранить данные, относящиеся к пользователю.
Шаг 1
Здесь недостаточно простого добавления зависимости. Нам нужно
- добавить плагин Protobuf и настроить Protobuf
- добавить зависимости Protobuf и Proto DataStore.
Шаг 2
Когда мы закончили настройку Gradle, перейдем к созданию прото-файла с обязательными полями. Создайте прото-каталог в app/src/main/
. Давайте добавим прототип файла в каталог proto с именем user_store
с расширением .proto
.
Шаг 3: Добавление содержимого в прото-файл.
Нам нужно определить версию, пакет, параметры java_multiple_files и определить наш объект сообщения с обязательными полями. Давайте сохраним два поля is_logged_in
типа Boolean и user_name
типа string. Как мы уже видели в разделе Protobuf, синтаксис прототипа файла будет таким же.
syntax = "proto3"; option java_package = "com.sample.android_sample_preference_datastore"; option java_multiple_files = true; message UserStore { bool is_logged_in = 1; string user_name = 2; }
Мы можем добавить несколько сообщений, в которых каждое отдельное сообщение имеет сгенерированный класс. Если у нас есть данные, связанные с приложением, мы можем создать AppData, а для пользовательского материала - UserStore и т. Д.
Шаг 4
Перестройте свой проект и убедитесь, что UserStore.java должен быть создан с использованием app/build/generated/source/proto
или двойной смены, и проверьте имя UserStore
. Просто просмотрите обзор UserStore
, где есть различные методы для хранения, извлечения данных, создания экземпляров UserStore
и прочего.
Шаг 5
Пришло время создать сериализатор. Давайте создадим класс, реализующий Serializer<T>
, где T
- это тип сообщения, определенный в файле proto. Это Serializer
говорит хранилищу данных, как читать и записывать тип данных, который мы определили в файле proto. Создадим UserStoreSerializer
Примечание. Лучше всего запускать блоки readFrom и writeTo внутри withContext (Dispatchers.IO) {} и обрабатывать исключения в обоих случаях, поскольку методы readFrom и writeTo могут вызывать исключение ввода-вывода. Нам нужно определить несколько сериализаторов, если есть несколько типов сообщений.
Шаг 6: Создание экземпляра Proto DataStore
Мы можем использовать dataStore
делегат для создания экземпляра Datastore. Делегату нужны два обязательных ввода: имя и сериализатор.
Делегат dataStore
гарантирует, что у нас есть единственный экземпляр DataStore с этим именем в нашем приложении.
Шаг 7. Считайте операцию из экземпляра прототипа хранилища данных.
Как и в случае с Preference Datastore, мы можем использовать DataStore.data
для отображения Flow
определенного свойства из сохраненного состояния экземпляра.
Для обработки исключений при чтении оберните блокировкой
Шаг 8: операция Wite на экземпляре хранилища данных прототипа
У нас есть updatedata()
функции, которые обновляют данные транзакционно в атомарной операции чтения-изменения-записи. Мы получаем текущее состояние свойства, затем записываем его и сохраняем.
Пример
Теперь давайте проверим их вместе на простом примере, как мы это сделали в случае хранилища данных о предпочтениях. Давайте сохраним и получим логическое значение (состояние входа пользователя в систему), используя шаблон репозитория внутри действия. В этом примере шаблон репозитория - это не что иное, как простой интерфейс и класс, реализующий интерфейс, в котором мы выполняем операции сохранения и выборки в экземпляре protoDataStore. Для простоты давайте вручную добавим экземпляр protoDataStore в реализацию репозитория. Поскольку мы продолжаем наблюдать текучесть, излучаемую хранилищем данных о предпочтениях, данные будут автоматически изменены.
Шаг 1
Давайте создадим простой XML с двумя кнопками для входа и выхода.
Шаг 2
Давайте создадим Activity, в котором мы раздуваем вышеуказанный макет и одним щелчком кнопки Login мы сохраняем состояние входа пользователя в систему как истинное, а при щелчке другого мы сохраняем false. Кроме того, мы создаем экземпляр proto DataStore, и будет следить за состоянием входа пользователя в систему. В зависимости от состояния мы добавляем текст и цвет фона
Нам нужно добавить зависимость lifecycle-runtime-ktx, чтобы использовать lifecycleScope.
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.3.1"
Шаг 3
Давайте создадим ProtoUserRepo с двумя методами для сохранения и получения состояния входа пользователя.
Шаг 4
Давайте предоставим ProtoUserRepoImpl реализацию ProtoUserRepo
Это все, что мы сделали. Запустите приложение и проверьте результат.
Вывод
Если у вас есть какие-либо проблемы при выполнении фрагментов кода, пожалуйста, посетите репозиторий GitHub для удобного доступа.
Резюме
Хранилища данных - это усовершенствованные решения для хранения данных. Proto Datastore использует прото-буферы и обеспечивает безопасность типов. Protobufs предназначены для сериализации и десериализации данных. Поскольку у него нет стабильной версии, подумайте дважды, прежде чем использовать его в приложениях. . Так что попробуйте ...
Спасибо за чтение…
Ресурсы
- "Хранилище данных"
- Android_sample_datastore