Realm android что это

Содержание
  1. Русские Блоги
  2. Царство Android
  3. Введение в Realm
  4. Быстрый старт
  5. установка
  6. модель
  7. Auto-Updating Objects
  8. Тип поля
  9. @ Требуемый модифицированный тип и нулевое значение (null)
  10. Игнорируемые атрибуты
  11. Auto-Updating Objects
  12. Атрибут индекса
  13. Первичные ключи
  14. Настройка объектов
  15. предел
  16. RealmModel интерфейс
  17. отношения
  18. Многие к одному
  19. Многие для многих
  20. Связанный запрос
  21. Напишите
  22. Создать объект
  23. Блок выполнения транзакции
  24. Асинхронная транзакция
  25. Обновить строку и байтовый массив
  26. Узнать
  27. Условия запроса
  28. Модификатор
  29. Логические операторы
  30. Сортировать
  31. Цепной запрос
  32. Автоматическое обновление результатов запроса
  33. Получать объекты по типу
  34. полимеризация
  35. Итерация
  36. удалять
  37. Асинхронный запрос
  38. Создать асинхронный запрос
  39. Зарегистрировать обратный звонок
  40. Проверьте, завершен ли запрос
  41. Принудительная загрузка асинхронного запроса
  42. Нить без петлителя
  43. Realms
  44. Область по умолчанию
  45. Настроить Realm
  46. Конфигурация области по умолчанию
  47. In-Memory Realm
  48. Dynamic Realm
  49. Закройте экземпляр Realm
  50. Автоматическое обновление
  51. Резьба
  52. Пример потока Realm
  53. Использовать Realm между потоками
  54. Уведомления
  55. Миграции
  56. шифрование
  57. адаптер
  58. Intents
  59. Связанный с многопоточным API Android Framework
  60. AsyncTask
  61. IntentService
  62. Поддержка других библиотек
  63. Сериализация
  64. Kotlin
  65. Retrofit
  66. Robolectric
  67. RxJava

Русские Блоги

Царство Android

Введение в Realm

realm — это кроссплатформенный движок мобильной базы данных, который поддерживает iOS, OS X (Objective-C и Swift) и Android. Позволяет эффективно писать код уровня модели приложения, чтобы обеспечить безопасное и быстрое хранение ваших данных.

Быстрый старт

установка

Для установки Realm как плагина Gradle необходимо выполнить два следующих шага:

  1. Добавьте следующую зависимость пути к классу в файл build.gradle проекта.
  1. Примените плагин realm-android в файле build.gradle приложения.
    apply plugin: ‘realm-android’

модель

Определение модели данных Realm необходимо унаследовать от класса RealmObject.

Модель данных Realm поддерживает не только частные переменные-члены, вы также можете использовать общедоступные, защищенные и настраиваемые методы-члены.

Auto-Updating Objects

Тип поля

Realm поддерживает следующие типы полей: boolean, byte, short, int, long, float, double, String, Date и byte []. Целочисленные типы short, int и long отображаются в Realm на один и тот же тип (на самом деле long). Кроме того, вы также можете использовать подклассы RealmObject и RealmList для представления отношения модели.

Объекты Realm также могут объявлять атрибуты упакованного типа, включая Boolean, Byte, Short, Integer, Long, Float и Double. Используя тип оболочки, к этим атрибутам можно получить доступ к нулевым значениям (null).

@ Требуемый модифицированный тип и нулевое значение (null)

В некоторых случаях значение null не подходит для атрибутов. В настоящее время вы можете использовать аннотацию @Required, чтобы указать Realm принудительно сохранить нулевые значения (null). Только Boolean, Byte, Short, Integer, Long, Float, Double, String, byte [] и Date могут быть изменены с помощью @Required. Использование модификации @Required для других типов атрибутов приведет к сбою компиляции. Базовые типы данных (примитивные типы) и RealmList не нуждаются в использовании аннотации @Required, поскольку сами по себе не могут иметь значение NULL. Свойство RealmObject всегда может быть пустым.

Игнорируемые атрибуты

Аннотация @Ignore означает, что поле не следует сохранять в Realm. Иногда входная информация содержит больше полей, чем модель, и вы не хотите иметь дело с этими неиспользуемыми полями данных, вы можете использовать @Ignore, чтобы определить эти поля, которые вы хотите игнорировать Realm.

Auto-Updating Objects

RealmObject будет обновляться в реальном времени и автоматически в соответствии с изменениями в базовых данных. Это означает, что вам не нужно повторно получать или обновлять RealmObject. Изменения в базовых данных со временем будут отражать соответствующие объекты или результаты запроса.

RealmObject и RealmResults не только работают быстрее и эффективнее, но и делают код более кратким и реактивным. Например, если ваша активность или фрагмент зависит от RealmObject или RealmResults, вам не нужно беспокоиться о том, когда обновлять или повторно запрашивать их для обновления пользовательского интерфейса — они будут обновляться автоматически.

Вы можете подписаться на уведомления Realm, чтобы знать, когда данные Realm обновляются, и обновлять ваш пользовательский интерфейс.

Атрибут индекса

Аннотация @Index добавит в поле поисковый индекс. Это замедлит скорость вставки и увеличит размер файла данных, но может ускорить запрос. Поэтому рекомендуется добавлять индексы только тогда, когда вам нужно ускорить запросы. В настоящее время только типы атрибутов, поддерживающие индексы, включают: String, byte, short, int, long, boolean и Date.

Первичные ключи

@PrimaryKey может использоваться для определения поля в качестве первичного ключа. Тип поля должен быть строковым (String) или целым числом (short, int или long) и их типом упаковки (Short, Int или Long). Не может быть нескольких первичных ключей. Использование в качестве первичного ключа типа атрибута, поддерживающего индексацию, также означает, что поле индексируется.

При создании объекта Realm для всех полей будут установлены значения по умолчанию. Чтобы избежать конфликтов с другим объектом с таким же первичным ключом, рекомендуется создать неуправляемый объект, присвоить значения полям, а затем использовать метод copyToRealm () для копирования объекта в Realm.
Существование первичного ключа означает, что вы можете использовать метод copyToRealmOrUpdate (). Он будет использовать этот первичный ключ, чтобы попытаться найти существующий объект. Если объект существует, он обновит объект; в противном случае он создаст его. Новый объект. Когда вызывающий объект copyToRealmOrUpdate () не имеет первичного ключа, будет выдано исключение.

Использование первичных ключей повлияет на производительность. Создание и обновление объектов будет происходить медленнее, а запросы — быстрее. Эти различия в производительности сложно определить количественно, потому что изменения в производительности тесно связаны с размером вашей базы данных.

Realm.createObject () вернет новый объект со всеми полями, установленными в значения по умолчанию. Если класс модели имеет первичный ключ, возможно, что значение по умолчанию первичного ключа возвращаемого объекта конфликтует с другими существующими объектами. Рекомендуется создать неуправляемый объект Realm, присвоить значение его первичному ключу, а затем вызвать copyToRealm (), чтобы избежать конфликтов.

Первичным ключам String и Wrapping Type (Short, Int или Long) может быть присвоено нулевое значение (null); если они также не изменены @Required.

Настройка объектов

Пользовательскому объекту RealmObject необходимо только расширить RealmObject и объявить соответствующее свойство как общедоступное. Сеттеры и геттеры не требуются, но доступ к свойствам осуществляется напрямую.

Вы можете использовать класс Dog напрямую, как и другие классы. createObject () и copyToRealm () могут помочь вам создать объект Dog, размещенный в Realm.

При необходимости вы можете добавить свою логику в сеттер и геттер. Например, перед сохранением может потребоваться проверить правильность значения. Кроме того, вы также можете добавить собственные методы в свой RealmObject.

предел

В настоящее время не поддерживаются окончательные, временные и изменчивые измененные переменные-члены. Это в основном предназначено для различения поведения объекта области, когда он неуправляемый (неуправляемый RealmObject).

Модель данных Realm не может быть унаследована от других объектов, кроме RealmObject. Но если вы его объявите, то конструктор должен быть пустым конструктором. В настоящее время это ограничение Realm. Но вы можете добавлять любые другие конструкторы.

RealmModel интерфейс

Помимо прямого наследования от RealmObject для объявления модели данных Realm, вы также можете объявить ее, реализовав интерфейс RealmModel и добавив модификатор @RealmClass.

Все методы RealmObject имеют соответствующие статические методы.

отношения

Любые два объекта RealmObject могут быть связаны друг с другом.

Вообще говоря, связь между RealmObjects не требует больших системных затрат. Обработка реляционных объектов в Realm очень эффективна и экономит память.

Многие к одному

Вам нужно только просто объявить свойство класса модели Realm:

Каждый объект контакта имеет 0 или 1 объект электронной почты. В Realm вы можете использовать один и тот же объект Email в нескольких объектах Contact по желанию. Точно так же этот пример также объясняет, как достичь взаимно-однозначных отношений.

Установка для свойства типа RealmObject нулевого значения (null) приведет к очистке ссылки на свойство, но не удалит соответствующий RealmObject.

Многие для многих

Вы можете связать 0 или более других объектов с объектом с помощью RealmList . Представьте, что у члена адресной книги есть несколько электронных писем:

Читайте также:  Как с айфона определить местонахождение андроида

RealmList — это контейнер объектов модели Realm, и его поведение почти такое же, как у обычного списка Java. Один и тот же объект модели Realm может существовать в нескольких RealmList. Один и тот же объект модели Realm может существовать несколько раз в одном RealmList. Вы можете использовать RealmList для представления отношений данных «один ко многим» и «многие ко многим».

Вы можете создавать объекты, а затем использовать RealmList.add () для добавления объектов электронной почты в контакт.

Иногда полезны рекурсивные отношения, что разрешено в Realm.

Конечно, при использовании рекурсивных отношений следует обратить внимание на проблему бесконечных циклов. Realm не проверяет вложенность циклов RealmList.

Установка для свойства типа RealmList значения null приведет к очистке списка, то есть длина списка станет равной 0. Но он не удалит ни один RealmObject в списке. Получатель RealmList никогда не вернет null. Возвращаемый объект всегда является экземпляром RealmList, но его длина может быть нулевой.

Связанный запрос

Realm поддерживает похожие запросы. Возьмем для примера следующую модель:

Каждый объект Person связан с несколькими объектами Dog, как показано в следующей таблице:

Давайте получим несколько объектов Person с помощью запроса на ассоциацию ——

Во-первых, обратите внимание, что имя поля equalsTo содержит связанный путь, разделенный знаком «.».

Напишите

Вы можете обращаться к объектам и запрашивать их в любое время (транзакции чтения неявны). Все операции записи (добавление, изменение и удаление объектов) должны быть включены в транзакцию записи (транзакцию). Транзакция записи может быть подтверждена или отменена. Во время отправки все изменения будут записаны на диск, и отправка будет успешной только тогда, когда все изменения могут быть сохранены. При отмене транзакции записи все изменения будут отменены. Использование транзакций записи обеспечит согласованность ваших данных.

Транзакции записи также используются для обеспечения безопасности потоков:

Когда вы имеете дело с объектами Realm в транзакции записи, вы можете столкнуться с ситуациями, когда вы хотите отменить изменения. Вы можете просто отменить транзакцию записи:

Обратите внимание, что транзакции записи будут блокировать друг друга. Если транзакция записи выполняется, транзакции записи других потоков будут блокировать их потоки. Использование транзакций записи в потоках пользовательского интерфейса и фоновых потоках одновременно может вызвать проблемы ANR. Вы можете использовать асинхронные транзакции, чтобы избежать блокировки потока пользовательского интерфейса.

Файлы данных Realm не будут повреждены из-за сбоев программы. Когда в блоке транзакции создается исключение, изменение данных, сделанное в текущей транзакции, будет отменено. Если программе необходимо продолжить работу в этой ситуации, вызовите cancelTransaction (), чтобы прервать транзакцию, или используйте executeTransaction (), чтобы выполнить транзакцию.

Благодаря архитектуре Realm MVCC, операция чтения не будет заблокирована во время выполнения транзакции записи! Это означает, что если вам не нужно выполнять параллельные операции записи из нескольких потоков, вы можете попытаться использовать более крупные транзакции записи, чтобы делать больше вещей, вместо нескольких меньших транзакций записи. Когда транзакция записи фиксируется в Realm, все другие экземпляры этого Realm будут уведомлены, а чтение неявной транзакции автоматически обновит каждый из ваших объектов Realm.

Доступ для чтения и записи в Realm соответствует требованиям ACID.

Создать объект

Поскольку объекты Realm сильно зависят от Realm, их следует создавать напрямую через Realm:

Или вы можете сначала создать экземпляр объекта, а затем добавить его, используя realm.copyToRealm (). Объекты Realm поддерживают несколько конструкторов, если один из них является общедоступным конструктором без параметров.

При использовании realm.copyToRealm () обратите внимание, что Realm управляет только возвращенным объектом, что очень важно. Любые изменения исходного объекта (umanaged Object) не будут записаны в Realm.

Блок выполнения транзакции

В дополнение к ручному вызову realm.beginTransaction (), realm.commitTransaction () и realm.cancelTransaction () вы можете использовать метод realm.executeTransaction (), который автоматически обрабатывает запуск и отправку записанной транзакции и отменяет ее при возникновении ошибки. Пишите вещи.

Асинхронная транзакция

Транзакции будут блокировать потоки друг друга, а открытие транзакций в фоновом потоке для операций записи может эффективно предотвратить блокировку потока пользовательского интерфейса. Используя асинхронные транзакции, Realm будет записывать операции в фоновом потоке и передавать результат обратно вызывающему потоку после завершения транзакции.

OnSuccess и OnError не должны быть перегружены. Перегруженная функция обратного вызова будет выполняться в потоке, в котором вызывается транзакция, когда транзакция завершается успешно или не выполняется. Функция обратного вызова выполняется через Looper, поэтому в потоках, отличных от Looper, разрешено использовать только нулевые функции обратного вызова.

Вызовы асинхронных транзакций вернут объект RealmAsyncTask. Вы можете использовать этот объект для отмены асинхронных транзакций при выходе из Activity или Fragment. Если вы обновите пользовательский интерфейс в функции обратного вызова, то, если вы забудете отменить асинхронную транзакцию, это может привести к сбою приложения.

Обновить строку и байтовый массив

Операция записи Realm предназначена для всей строки или атрибута байтового массива, а не для отдельных элементов атрибута. Предположим, вам нужно изменить пятый символ в массиве байтов, вам нужно:

Узнать

Все операции чтения (включая запросы) в Realm выполняются с задержкой, и данные никогда не будут скопированы.
Использовать класс пользователя —

Например, чтобы найти всех пользователей с именем Джон или Питер, вы можете написать:

Запрос возвращает экземпляр RealmResults, который содержит пользователей с именами Джон и Питер.Эти объекты не являются копиями, то есть вы получаете список соответствующих ссылок на объекты, и все операции с соответствующими объектами применяются непосредственно к исходным объектам.. RealmResults наследуется от AbstractList Java и ведет себя аналогичным образом. Например, вы можете получить доступ к одному из объектов через index.

Если в запросе нет совпадений, возвращаемый объект RealmResults не будет иметь значение null, вместо этого его метод size () вернет 0.

Изменение или удаление любого объекта в RealmResults должно быть выполнено в транзакции записи.

Условия запроса

Realm поддерживает следующие условия запроса:

  • between (), betterThan (), lessThan (), betterThanOrEqualTo () и lessThanOrEqualTo ()
  • equalTo () и notEqualTo ()
  • содержит (), начинается с () и заканчивается с ()
  • isNull () и isNotNull ()
  • isEmpty () и isNotEmpty ()

Модификатор

В условиях строкового запроса можно игнорировать регистр букв A-Z и a-z с помощью модификатора Case.INSENSITIVE.

Логические операторы

Каждое условие запроса будет неявно объединено логическим и (&), а логическое или (или) должно быть явно выполнено или ().

Кроме того, вы также можете использовать not () для отмены условия. Оператор not () может использоваться с beginGroup () / endGroup () для отмены подусловий.

Сортировать

После выполнения запроса и получения результатов его можно отсортировать:

Цепной запрос

Поскольку результаты запроса не будут скопированы и не будут выполняться при отправке запроса, вы можете связать запрос и постепенно сортировать и фильтровать:

Вы также можете использовать цепные запросы к дочерним объектам. Предположим, что вышеупомянутый объект Person содержит список объектов Dog:

Вы можете запросить, чтобы узнать всех людей в возрасте от 13 до 20 лет, у которых есть хотя бы одна годовалая собака:

Обратите внимание, что цепочка запросов в конечном итоге построена на RealmResults, а не на RealmQuery. Если вы добавляете дополнительные условия запроса в существующий RealmQuery, вы изменяете сам запрос, а не цепочку запросов.

Автоматическое обновление результатов запроса

RealmResults — это автоматически обновляемое представление содержащихся в нем данных, что означает, что его никогда не нужно запрашивать повторно. Изменение объекта данных будет отражено в соответствующем результате запроса в следующем событии Looper.

Это справедливо для всех RealmResults — независимо от того, есть ли условие фильтрации или цепной запрос.

Эта функция RealmResults не только делает Realm быстрым и эффективным, но и делает ваш код более лаконичным. Например, если ваше действие или фрагмент зависит от определенного результата запроса, вы можете сохранить соответствующий объект Realm или RealmResults как свойство. Вам не нужно определять, обновляется ли он каждый раз, когда вы посещаете его — Realm гарантирует это .

Читайте также:  Android which app notification

Вы можете подписаться на уведомления Realm, чтобы знать, что данные Realm были обновлены, а затем обновить пользовательский интерфейс, не запрашивая повторно для получения RealmResults.

Из-за функции автоматического обновления результатов запроса не полагайтесь на фиксированные индексы (индексы) и постоянное количество записей.

Получать объекты по типу

Самый простой метод извлечения объектов из Realm — это realm.where (Foo.class) .findAll (), который возвращает RealmResults, содержащий все объекты запрашиваемого класса модели.

Также существует findAll (), который предоставляет функцию сортировки. Подробнее см. Realm.where (Foo.class) .findAllSorted ().

полимеризация

RealmResult имеет несколько методов агрегирования:

Итерация

Вы можете просмотреть RealmResults следующим образом:

Или используйте цикл for:

Автоматическое обновление RealmResults будет запускаться событием цикла, но до того, как событие прибудет, некоторые элементы могут больше не соответствовать условиям запроса или они были удалены.

Чтобы избежать этой проблемы, вы можете использовать метод deleteFromRealm () RealmResults:

удалять

Вы можете удалить данные из результатов запроса:

Асинхронный запрос

Вы можете использовать фоновый поток для запроса.

Большинство запросов Realm достаточно быстрые, чтобы их можно было использовать в потоке пользовательского интерфейса без каких-либо задержек. Но если вам нужно выполнять очень сложные запросы или запросы к большим объемам данных, было бы неплохо использовать фоновые потоки для запросов.
Пример. Найдите пользователя по имени «Джон» или «Питер».

Создать асинхронный запрос

Обратите внимание, что здесь вызов не блокируется, а сразу возвращает RealmResults . Это очень похоже на концепцию Future в стандартной Java. Запрос будет выполнен в фоновом потоке, и когда он будет завершен, ранее возвращенный экземпляр RealmResults будет обновлен.

Если вы хотите получать уведомление о завершении запроса и обновлении RealmResults, вы можете зарегистрировать RealmChangeListener. Этот слушатель будет вызываться при обновлении RealmResults (обычно после фиксации транзакции).

Зарегистрировать обратный звонок

Пожалуйста, удалите регистрацию слушателя при выходе из Activity или Fragment, чтобы избежать утечки памяти.

Проверьте, завершен ли запрос

Метод isLoaded экземпляра RealmResults, возвращенный синхронным запросом, всегда будет возвращать значение true.

Принудительная загрузка асинхронного запроса

При желании вы можете дождаться завершения асинхронного запроса, который заблокирует текущий поток и сделает запрос синхронным (концепция, аналогичная Future.get ()).

Нить без петлителя

Вы можете использовать асинхронные запросы в потоках Looper. Асинхронный запрос должен использовать обработчик для доставки результатов запроса. Использование асинхронных запросов в потоках без Looper вызовет выброс исключения IllegalStateException.

Realms

Область (области) — это то, что мы называем базой данных: она содержит множество различных объектов и соответствует файлу на диске. Перед использованием необходимо инициализировать библиотеку Realm:
Realm.init(context);
Для инициализации Realm необходимо предоставить объект контекста Android. Операцию инициализации нужно выполнить только один раз. Рекомендуется наследовать от Application и инициализировать в перегруженном методе onCreate ().

Не забудьте изменить AndroidManifest.xml:

Область по умолчанию

Вы могли заметить, что мы всегда обращаемся к нашим инициализированным переменным области через Realm.getInstance (this). Этот статический метод вернет экземпляр Realm для вашего текущего потока, который соответствует файлу default.realm в вашем каталоге Context.getFilesDir ().

Этот файл находится в доступном для записи корневом каталоге вашего приложения. По умолчанию Realm использует внутреннее хранилище, и вашему приложению не нужно получать какие-либо разрешения на чтение и запись. Как правило, этот файл находится в / data / data /

/ files /.
Абсолютный путь к области можно получить с помощью realm.getPath ().

Важно отметить, что экземпляр Realm является одноэлементным многопоточным, то есть, если вы вызываете статический метод несколько раз в одном потоке для получения Realm для одного и того же пути, будет возвращен тот же экземпляр Realm.

Настроить Realm

RealmConfiguration используется для настройки различных функций создаваемой области. Самая простая конфигурация выглядит следующим образом:
RealmConfiguration config = new RealmConfiguration.Builder().build();
Область, настроенная, как указано выше, будет сохранена в Context.getFilesDir () и названа default.realm.

Типичная конфигурация выглядит следующим образом:

У вас также может быть несколько RealmConfigurations. Таким образом, вы можете контролировать версию, схему и путь Realm.

Конфигурация области по умолчанию

RealmConfiguration можно сохранить как конфигурацию по умолчанию. Установив конфигурацию области по умолчанию в настраиваемом приложении, вы можете более легко создать область для конфигурации по умолчанию в другом месте кода.

In-Memory Realm

Определите непостоянный экземпляр Realm, существующий в памяти:

Таким образом, можно создать Сфера, которая существует в «памяти». Область «в памяти» может по-прежнему использовать дисковое хранилище, когда память ограничена, но дисковое пространство будет освобождено, когда экземпляр области будет полностью закрыт.

Обратите внимание, что нельзя создавать одновременно область «в памяти» и обычную (постоянную) область с одним и тем же именем.

Когда все ссылки на экземпляры области «в памяти» освобождаются, данные в этой области также будут очищены. Рекомендуется сохранять ссылку на экземпляр Realm в памяти в течение жизненного цикла приложения, чтобы избежать непредвиденной потери данных.

Dynamic Realm

Для обычного Realm модель данных определяется как подкласс RealmObject. Это обеспечивает безопасность типов, но иногда некоторые модели данных недоступны во время компиляции. Например, при переносе данных (миграции) или файлах CSV.

DynamicRealm — это вариант обычного Realm. Он может управлять данными Realm без подкласса RealmObject. Его доступ к данным основан на определении строк вместо RealmObject.

При создании Dynamic Realm используется та же RealmConfiguration, что и при создании обычного Realm, но процесс его создания игнорирует проверку схемы, миграции и версии схемы.

DynamicRealm предлагает большую гибкость за счет безопасности типов и производительности. Пожалуйста, используйте его, когда вам действительно нужна такая гибкость.

Закройте экземпляр Realm

Realm реализует интерфейс Closeable для освобождения собственной памяти и файловых дескрипторов. Обязательно закройте экземпляр Realm после его использования.

Экземпляры Realm основаны на подсчете ссылок, что означает, что если вы вызываете getInstance () дважды в одном потоке, вам нужно дважды вызвать close (), чтобы закрыть экземпляр. Например, если вам нужно реализовать Runnable, просто вызовите getInstance () в начале функции и close () в конце функции!

Для потока пользовательского интерфейса вы можете выбрать вызов realm.close () в методе onDestroy ().

Если вы хотите использовать потоки Looper, отличные от потоков пользовательского интерфейса, вы можете обратиться к следующему коду:

Вот хороший пример для AsyncTask:

Если вы хотите использовать Thread и Runnable для краткосрочных задач, обратитесь к следующему коду:

Если вам повезло работать с minSdkVersion> = 19 и Java> = 7, вы можете использовать try-with-resources:

Автоматическое обновление

Если экземпляр Realm существует в потоке с Looper, то этот экземпляр Realm имеет функцию автоматического обновления. Это означает, что при изменении в базе данных Realm экземпляр Realm будет автоматически обновлен в следующем цикле событий. Эта удобная функция позволяет обеспечить синхронизацию пользовательского интерфейса и данных в режиме реального времени без особых усилий.

Если поток экземпляра Realm не привязан к Looper, то экземпляр не будет обновлен, пока вы вручную не вызовете метод waitForChange (). Обратите внимание, что отказ от обновления Realm для сохранения ссылок на старые данные приведет к дополнительным накладным расходам на диск и память. Это также важная причина, по которой close () вызывается для закрытия экземпляра Realm при завершении потока.

Если вы хотите определить, имеет ли текущий экземпляр Realm функцию автоматического обновления, вы можете запросить его, вызвав метод isAutoRefresh ().

Резьба

На самом деле, вам не так много вещей нужно знать об использовании Realm между потоками. Ключевым моментом является то, что благодаря функции мгновенного обновления объектов и запросов вам не нужно беспокоиться о согласованности и эффективности данных при многопоточности.

Вы можете читать и записывать объекты Realm в разных потоках в реальном времени, не беспокоясь о других потоках, работающих с одним и тем же объектом. Вам нужно использовать транзакции при изменении объекта, и данные, указывающие на тот же объект в другом потоке, будут обновлены мгновенно (обновление будет выполнено в следующем цикле событий).

Читайте также:  Агент регистрация для андроид

Единственное ограничение — вы не можете произвольно передавать объекты Realm между потоками. Если вы используете тот же объект в другом потоке, используйте запрос, в котором поток извлекает объект. Имейте в виду, что все объекты Realm будут обновляться в разных потоках — Realm уведомит вас об изменении данных.

Пример потока Realm

Предположим, наше приложение хочет отобразить список пользователей. Мы получаем новых пользователей с пульта дистанционного управления в фоновом потоке (Android IntentService) и сохраняем их в Realm. Но когда фоновый поток сохраняет нового пользователя, данные в потоке пользовательского интерфейса будут автоматически обновлены. Поток пользовательского интерфейса будет уведомлен через RealmChangeListener, а затем поток пользовательского интерфейса должен обновить соответствующие элементы управления. Благодаря функции автоматического обновления Realm нет необходимости повторно запрашивать данные.

После добавления нового пользователя в фоновую службу список клиентов будет автоматически обновляться без каких-либо действий с вашей стороны. То же самое верно и для одного RealmObject. Предположим, вам нужно управлять объектом Realm, вам нужно только обновить его данные в одном потоке, и поток пользовательского интерфейса автоматически получит обновленные данные. Если вам нужно отвечать на обновления данных, просто добавьте слушателя, как мы это сделали в приведенном выше коде.

Использовать Realm между потоками

Помните: экземпляры Realm, RealmObject и RealmResults нельзя использовать в нескольких потоках. Но вы можете использовать асинхронные запросы и асинхронные транзакции, чтобы поместить часть операции в фоновый поток, и вызывающий поток получает уведомление о получении результата по завершении.

Когда вам нужно получить доступ к одной и той же части данных в потоках, просто повторно получите экземпляр Realm в этом потоке (например, Realm.getInstance (конфигурация RealmConfiguration) или другие аналогичные методы), а затем запросите через этот экземпляр Realm, чтобы получить то, что вам нужно. Данные. Объект, полученный запросом, будет сопоставлен с теми же данными в Realm, и объект, полученный этим методом, может быть прочитан и записан в любом месте его потока!

Вы можете напрямую добавлять объекты JSON в Realm. Эти объекты JSON могут бытьString,Один JSONObject ИлиInputStream. Realm будет игнорировать поля, которые существуют в JSON, но не определены в классе модели Realm. Отдельные объекты можно добавлять через Realm.createObjectFromJson (). Список объектов можно добавить через Realm.createAllFromJson ().

Уведомления

Слушатель работает только с потоком Looper. Для потоков без цикла используйте Realm.waitForChange ().

Когда фоновый поток добавляет данные в Realm, ваш поток пользовательского интерфейса или другие потоки могут добавить слушателя для получения уведомлений об изменениях данных. Слушатель будет запускаться при изменении данных Realm.

Вы можете легко удалить всех слушателей.
realm.removeAllChangeListeners();

Помимо добавления слушателей в экземпляры Realm, вы также можете добавить слушателей в экземпляры RealmObject и RealmResults. Таким образом можно отслеживать изменения объектов и результатов запроса. Кроме того, когда вызывается функция обратного вызова слушателя, соответствующие данные были обновлены, и вам не нужно выполнять операцию обновления.

Наконец, эти слушатели также будут запускаться при изменении ссылочного объекта объекта слушателя, см. Пример:

Миграции

Все базы данных должны иметь дело с изменениями модели. Модель данных Realm определяется стандартными объектами Java. Изменение модели данных требует только изменения определения объекта данных.

Если старого файла данных Realm нет, то изменение кода будет отражать соответствующее изменение файла данных Realm. Однако, если старая версия файла данных Realm уже существует, Realm выдаст исключение, чтобы указать, что файл базы данных необходимо перенести. Установите версию схемы и код миграции в соответствующей RealmConfiguration, чтобы обрабатывать ее правильно и избежать возникновения исключения.

Приведенный выше пример позволяет автоматически выполнять соответствующий код миграции при необходимости миграции. Мы предоставляем связанные API-интерфейсы для обновления сохраненной схемы и данных, соответствующих предыдущей схеме.

Если старого файла данных Realm нет, миграция не требуется.В этом случае Realm создаст новый файл данных с суффиксом .realm на основе новой объектной модели. Если в процессе разработки и отладки вам нужно часто менять модель данных и вы не против потери старых данных, вы можете напрямую удалить файл .realm (который содержит все данные!), Не беспокоясь о миграции. Это очень полезно на ранних этапах разработки вашего приложения.

шифрование

Файлы области можно зашифровать и сохранить на диске, передав параметр ключа размером 512 бит (64 байта) в Realm.getInstance (). EncryptionKey ().

Это гарантирует, что все данные, постоянно хранящиеся на диске, зашифрованы по стандарту AES-256.Каждый раз, когда вы создаете новый экземпляр Realm, вам нужно предоставлять один и тот же ключ

адаптер

Realm предоставляет некоторые абстрактные классы инструментов для удобного отображения OrderedRealmCollection (RealmResults и RealmList реализуют это оправдание) в элементах управления пользовательского интерфейса.

  • RealmBaseAdapter можно использовать с ListView.
  • RealmRecyclerViewAdapter можно использовать с RecyclerView

Чтобы использовать эти адаптеры, вам необходимо добавить дополнительные зависимости в build.gradle приложения.

Intents

Поскольку вы не можете передать RealmObject напрямую через намерение, мы рекомендуем передавать только идентификатор RealmObject. В качестве распространенного примера, если ваш объект имеет первичный ключ, пожалуйста, передайте значение первичного ключа через связку намерения.

Получатель (Activty, Service, IntentService, BroadcastReceiver и другие) разрешает первичный ключ из пакета, а затем открывает запрос Realm для получения RealmObject.

Связанный с многопоточным API Android Framework

Метод doInBackground () AsyncTask будет выполняться в фоновом потоке. Метод onHandleIntent (Intent intent) IntentService будет выполняться в фоновом рабочем потоке.

Если вам нужно использовать Realm в этих методах, закройте экземпляр Realm после завершения вызова Realm.

AsyncTask

Откройте и закройте Realm в методе doInBackground следующим образом:

IntentService

ChangeListener не будет работать в IntentService. Хотя IntentService сам по себе является потоком Looper, каждый вызов onHandleIntent является независимым событием. Вы можете зарегистрировать вызовы слушателя, которые не будут возвращать ошибку, но никогда не будут запускаться.

Откройте и закройте Realm в методе onHandleIntent (), как показано ниже:

Поддержка других библиотек

GSON — это библиотека обработки JSON, разработанная Google. GSON и Realm могут работать вместе.

Сериализация

Иногда вам нужно сериализовать и десериализовать объект Realm для работы с другими библиотеками (такими как Retrofit). Поскольку GSON использует значения переменных-членов вместо методов получения и установки, вы не можете сериализовать объекты Realm с помощью общих методов GSON.
Вам необходимо настроить JsonSerializer для объектов модели Realm и зарегистрировать его как TypeAdapter.

Kotlin

Retrofit

Realm может без проблем работать с Retrofit 1.x и 2.x. Но учтите, что Retrofit не сохраняет объект в Realm автоматически. Вам нужно сохранить их в Realm, вызвав Realm.copyToRealm () или Realm.copyToRealmOrUpdate ().

Robolectric

RxJava

Realm включает встроенную поддержку RxJava. Следующие классы могут быть представлены как Observable: Realm, RealmResults, RealmObject, DynamicRealm и DynamicRealmObject.

Здесь следует отметить, что официальные примеры могут нормально работать только в модификации 1.x, но не в модификации 2.x.
Причина: api.user в retrofit1.x по умолчанию работает в рабочем потоке, но для retrofit2.x требуется рабочий поток, поэтому вам нужно определить рабочий поток после api.user (), но он не может Поток указан вне flatMap, поскольку к области нельзя получить доступ для нескольких потоков, как показано ниже:

Из приведенного выше кода видно, что он добавляется сразу после запроса на модернизацию сети. subscribeOn(Schedulers.io());

Обратите внимание, что асинхронный запрос не будет блокировать текущий поток. Приведенный выше код немедленно вернет экземпляр RealmResults. Если вы хотите убедиться, что RealmResults загружен, используйте оператор фильтра и метод RealmResults .isLoaded (). Судя, загружен ли RealmResults, вы можете узнать, был ли выполнен запрос.

Источник

Оцените статью