Обновить область в проекте Android

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

Я особенно обеспокоен миграциями, так как API для миграций, казалось, немного изменился с момента написания моего кода, и я не уверен, что мои миграции прекратятся, если я просто обновлю свою версию. К сожалению, на их веб-странице нет документации по обновлению версии Realm.

У кого-нибудь есть опыт обновления Realm, особенно увеличение версии по сравнению с двумя основными версиями?

2 ответа

Список критических изменений доступен в CHANGELOG.MD на их Github.

Тем не менее, стоит отметить, что на дороге было довольно много переломных изменений, особенно отметив 0.89.0.

От 0.82.0 в 5.1.0 является следующим (который является наиболее стабильной версией на данный момент):

0.82.0:

BREAKING CHANGE: Поля с аннотацией @PrimaryKey теперь индексируются автоматически. Старые схемы требуют миграции.

(0.82.2 был наиболее стабильным здесь, но он не работал на устройствах Blackberry. Первая стабильная версия для использования на Blackberry была 0.87.2.)

В версии 0.86.0+ вы можете добавить индекс к аннотированному полю, используя

@Override
public void migrate(final DynamicRealm realm, long oldVersion, long newVersion) {
    RealmSchema schema = realm.getSchema();
    // version check and stuff
    RealmObjectSchema personSchema = schema.get("Person");
    personSchema.addIndex("fieldName");

0,83:

BREAKING CHANGE: Обновление формата файла базы данных. Файл Realm, созданный этой версией, не может быть использован предыдущими версиями Realm.

BREAKING CHANGE: Удалены устаревшие методы и конструкторы из класса Realm.

BREAKING CHANGE: введены в штучной упаковке типы Boolean, Byte, Short, Integer, Long, Float и Double. Добавлена ​​нулевая поддержка. Введенная аннотация @Required для обозначения поля не обнуляема. String, Date и byte[] стали обнуляемыми по умолчанию, что означает, что RealmMigrationNeededException будет выброшено, если будет открыта предыдущая версия файла Realm.

О, мальчик, это хороший. Поддержка NULL.

Штучные типы для примитивов стали доступны. Типы в штучной упаковке обнуляются по умолчанию. Все String, Date, а также byte[] должен быть аннотирован @Required, или же schema.setNullable("fieldName", nullability) и сделать их всех обнуляемыми.

0.84.0:

Добавлены асинхронные запросы. Здесь нет ничего нового с точки зрения схемы.

0.85.0:

BREAKING CHANGE: удалено исключение RealmEncryptionNotSupportedException, поскольку реализация шифрования изменилась в базовом механизме хранения Realm. Шифрование теперь поддерживается на всех устройствах.

BREAKING CHANGE: Realm.executeTransaction () теперь напрямую выбрасывает любое RuntimeException вместо его оборачивания в RealmException (# 1682).

BREAKING CHANGE: RealmQuery.isNull () и RealmQuery.isNotNull() теперь генерируют IllegalArgumentException вместо RealmError, если имя поля является связанным полем, а последний элемент является ссылкой (#1693).

Ничего важного здесь пока нет, хотя:

Установщики в управляемом объекте для RealmObject и RealmList теперь генерируют исключение IllegalArgumentException, если значение содержит недопустимый (неуправляемый, удаленный, закрытый, из другого Realm) объект (#1749).

Этот интересный. Ранее это просто не удалось, так что это к лучшему. Но это тоже самое большое ограничение Царства.

0.86.0:

BREAKING CHANGE: API-интерфейс миграции был заменен новым API.

BREAKING CHANGE: константы RealmResults.SORT_ORDER_ASCENDING и RealmResults.SORT_ORDER_DESCENDING заменены на перечисления Sort.ASCENDING и Sort.DESCENDING.

BREAKING CHANGE: константы RealmQuery.CASE_SENSITIVE и RealmQuery.CASE_INSENSITIVE заменены на перечисления Case.SENSITIVE и Case.INSENSITIVE.

BREAKING CHANGE: Realm.addChangeListener, RealmObject.addChangeListener и RealmResults.addChangeListener содержат сильную ссылку на слушателя, вы должны отменить регистрацию слушателя, чтобы избежать утечек памяти.

BREAKING CHANGE: Удалены устаревшие методы RealmQuery.minimum{Int,Float,Double}, RealmQuery.maximum{Int,Float,Double}, RealmQuery.sum{Int,Float,Double} и RealmQuery.average{Int,Float,Double}. Используйте взамен RealmQuery.min(), RealmQuery.max(), RealmQuery.sum() и RealmQuery.average().

BREAKING CHANGE: Удален RealmConfiguration.getSchemaMediator(), который по ошибке открыт. И RealmConfiguration.getRealmObjectClasses() добавляется в качестве альтернативы для получения набора классов модели (# 1797).

BREAKING CHANGE: Realm.addChangeListener, RealmObject.addChangeListener и RealmResults.addChangeListener генерируют исключение IllegalStateException при вызове в потоке без лупера. Это должно предотвратить регистрацию слушателей, которые не будут вызваны.

Добавлен новый Dynamic API с использованием DynamicRealm и DynamicRealmObject.

Добавлены Realm.getSchema() и DynamicRealm.getSchema().

Новый API-интерфейс миграции, использующий DynamicRealm вместо Realm.getTable(),

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

0.87.0:

Поддержка RX. Ничего важного.

0.87.2:

Убран явный вызов GC при совершении транзакции (#1925).

Наконец, Realm снова стал стабильным!:)

0.88.0:

Ломать изменения

Realm теперь должен быть установлен как плагин Gradle.

DynamicRealm.executeTransaction () теперь напрямую генерирует любое RuntimeException вместо его оборачивания в RealmException (# 1682).

DynamicRealm.executeTransaction () теперь генерирует исключение IllegalArgumentException вместо молча принятия нулевого объекта Transaction.

Установщики строк теперь генерируют IllegalArgumentException вместо RealmError для недопустимых суррогатов.

DynamicRealm.distinct()/diverAsync() и Realm.distinct()/diverAsync() теперь генерируют исключение IllegalArgumentException вместо UnsupportedOperationException для недопустимого типа или неиндексированного поля.

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

Удален RealmConfiguration.getSchemaMediator() из публичного API, который устарел в 0.86.0. Пожалуйста, используйте RealmConfiguration.getRealmObjectClasses(), чтобы получить набор классов модели (# 1797).

Realm.migrateRealm () создает исключение FileNotFoundException, если файл Realm не существует.

Теперь необходимо отписаться от всех наблюдаемых RxJava Царств, чтобы полностью закрыть Царство (# 2357).

Welp. Теперь это AAR. Вы должны добавить к classpath и запустить его с apply plugin: 'realm-android' вместо compile ... зависимость.

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

Улучшения

Поддержка пользовательских методов, пользовательской логики в средствах доступа, имен пользовательских средств доступа, реализации интерфейса и открытых полей в объектах Realm (#909).

Улучшена загрузка.so с помощью ReLinker.

Это совершенно необходимо, поэтому я бы не хотел застрять на 0.87.5 наверняка.

0.89.0:

Ломать изменения

Значение поля @PrimaryKey теперь может быть пустым для типов String, Byte, Short, Integer и Long. Старые области необходимо перенести, используя RealmObjectSchema.setNullable() или добавив аннотацию @Required. (# 2515).

RealmResults.clear () теперь генерирует исключение UnsupportedOperationException. Вместо этого используйте RealmResults.deleteAllFromRealm().

RealmResults.remove (int) теперь генерирует исключение UnsupportedOperationException. Вместо этого используйте RealmResults.deleteFromRealm(int).

RealmResults.sort () и RealmList.sort() теперь возвращают отсортированный результат вместо сортировки на месте.

RealmList.first () и RealmList.last() теперь генерируют ArrayIndexOutOfBoundsException, если RealmList пуст.

Удален устаревший метод Realm.getTable() из общедоступного API.

Realm.refresh () и DynamicRealm.refresh() на Looper больше не имеют никакого эффекта. RealmObject и RealmResults всегда обновляются в следующем цикле событий.

Хорошо, это самый грязный.

1.) вы должны добавить @Required аннотация для @PrimaryKey аннотированные поля, потому что null является допустимым значением первичного ключа.

2.) realm.refresh() больше не работает. Это будет удалено в любом случае. Вот обходной путь для 1.1.1, хотя, должен использоваться только в фоновых потоках. Впрочем, он снова доступен в Realm 3.2.

3.) getTable() устранен. Не используйте это. Используйте новый API миграции.

4.) realmResults.sort() возвращает новый RealmResults, к которому также должен быть добавлен прослушиватель изменений. Я думаю, что это ненадежно, поэтому я бы просто использовать findAllSorted() вместо.

5.) Вы можете не думать об этом, но

RealmObject и RealmResults всегда обновляются в следующем цикле событий. (ПРИМЕЧАНИЕ: ЭТО НЕ ДАЛЕЕ ИСТИННО, ПОСЛЕ РЕАЛЬНОСТИ 3.1+, ГДЕ ИЗМЕНЯЮТСЯ СЛУЧАИ ИЗМЕНЕНИЯ ВНОВЬ НА commitTransaction())

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

RealmResults как известно, обновляются только после добавления RealmChangeListener называется. В 1.1.1, когда RealmChangeListener Все результаты были обновлены.

Это изменение, однако, также изменило поведение итераций в транзакциях. В транзакциях вы всегда видели новейшую версию. Это означало, что запрос был переоценен во время итерации и изменения элементов. (ЭТО ТАКЖЕ ДЕЛО С РЕАЛЬНЫМ 3.0)

Пример, ранее это был действительный код:

RealmResults<Stuff> stuffs = realm.where(Stuff.class).equalTo("something", false).findAll();
while(!stuffs.isEmpty()) {
    stuffs.get(0).setSomething(true);
}
// you end up here because stuffs will be empty 
// because of live auto-updates in transactions

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

RealmResults<Stuff> stuffs = realm.where(Stuff.class).equalTo("something", false).findAll();
for(int i = 0; i < stuffs.size(); i++) {
    stuffs.get(i--).setSomething(true);
}
// I end up here because of live auto-updates

Это проблема, потому что stuffs больше не будет меняться. Я должен был сделать поиск -- в моем коде и исправить все итерации, как это.

Официальный обходной путь был таким:

RealmResults<Stuff> stuffs = realm.where(Stuff.class).equalTo("something", false).findAll();
for(int i = stuffs.size()-1; i >= 0; i--) {
    stuffs.get(i).setSomething(true);
}
// I end up here because of normal iteration

Это все равно будет хорошо работать в 0.89.0.

Начиная с версии 0.89.0, это также допустимый код (а в версии 3.0.0+ автоматически создается коллекция снимков):

RealmResults<Stuff> stuffs = realm.where(Stuff.class).equalTo("something", false).findAll();
for(Stuff stuff : stuffs) {
    stuff.setSomething(true);
}

Элементы в результатах все еще становятся недействительными, но сами результаты не меняются. (Это относится и к коллекциям снимков в Realm 3.0.0+).

0.90.0:

Ломать изменения

RealmChangeListener также предоставляет измененный объект / область / коллекцию (#1594).

Все методы JSON в Realm теперь только оборачивают JSONException в RealmException. Все остальные исключения выдаются такими, какие они есть.

Помечены все методы в RealmObject и все открытые классы final (#1594).

Удален BaseRealm из общедоступного API.

Удален HandlerController из общедоступного API.

Удален конструктор RealmAsyncTask из общедоступного API (#1594).

RealmBaseAdapter был перемещен в свой собственный репозиторий GitHub: https://github.com/realm/realm-android-adapters

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

Так RealmBaseAdapter сейчас в realm-android-adapters, за 1.1.1 царства, использовать 1.3.0, Также добавляет RealmRecyclerViewAdapter, За 3.5.0 использовать 2.0.0 или новее.

RealmChangeListeners получил element параметр. Ура.

Кроме того, дата теперь имеет milisecond точность.

0.91.0:

Ломать изменения

Удалены все методы @Deprecated.

Вызов Realm.setAutoRefresh() или DynamicRealm.setAutoRefresh() из потока без лупера создает исключение IllegalStateException, даже если autoRefresh имеет значение false (#2820).

Устаревшее множество методов в 0.90.0, поэтому

Главные изменения:

Realm.allObjects * (). Вместо этого используйте Realm.where(clazz).findAll*().

Realm.distinct * (). Вместо этого используйте Realm.where(clazz).distinct*().

DynamicRealm.allObjects * (). Вместо этого используйте DynamicRealm.where(className).findAll*().

DynamicRealm.distinct * (). Вместо этого используйте DynamicRealm.where(className).distinct*().

Realm.allObjectsSorted (поле, сортировка, поле, сортировка, поле, сортировка). Используйте взамен RealmQuery.findAllSorted(field[], sort[])`.

RealmQuery.findAllSorted (поле, сортировка, поле, сортировка, поле, сортировка). Используйте взамен RealmQuery.findAllSorted(field[], sort[])`.

RealmQuery.findAllSortedAsync (поле, сортировка, поле, сортировка, поле, сортировка). Вместо этого используйте RealmQuery.findAllSortedAsync(field[], sort[])`.

RealmConfiguration.setModules (). Вместо этого используйте RealmConfiguration.modules().

Realm.refresh () и DynamicRealm.refresh(). Вместо этого используйте Realm.waitForChange()/stopWaitForChange() или DynamicRealm.waitForChange()/stopWaitForChange().

waitForChange() на самом деле не работает, так как люди намерены использовать его, так что вот обходной путь для 1.1.1 до 3.1.4, хотя, должен использоваться только в фоновых потоках. refresh() будет повторно добавлен в 3.2.0.

Также в какой-то момент Realm.getInstance(Context) был удален, используйте Realm.getInstance(new RealmConfiguration.Builder(Context).build()) вместо.


После этого вышла 1.0.0, так что это в значительной степени именно так.

Кстати, в 1.1.0 insertOrUpdate() был добавлен, что быстрее, чем copyToRealmOrUpdate() и не возвращает прокси.


2.0.2:

  • Первичные ключи являются неизменяемыми для управляемых объектов, после того как они установлены, их нельзя изменить, и при попытке выдается исключение. Также используйте realm.createObject(clazz, primaryKeyValue) если вы используете createObject() создавать объекты.

  • Вы должны позвонить Realm.init(Context) в какой-то момент.

  • Конфигуратор больше не получает Контекст.

  • armeabi больше не поддерживается. (только v7a и остальные)


Никаких критических изменений до 3.0.0, но куча исправлений.


3.0.0:

RealmResults.distinct () возвращает новый объект RealmResults вместо фильтрации по исходному объекту (# 2947).

RealmResults постоянно обновляется автоматически. Любая транзакция в текущем потоке, которая может повлиять на порядок или элементы RealmResults, немедленно изменит RealmResults, а не изменит его в следующем цикле событий. Стандартный RealmResults.iterator () будет продолжать работать в обычном режиме, что означает, что вы все равно можете удалять или изменять элементы, не влияя на итератор. То же самое не верно для простых циклов for. В некоторых случаях простой цикл for не будет работать ( https://realm.io/docs/java/3.0.0/api/io/realm/OrderedRealmCollection.html), и вы должны использовать новый createSnapshot() метод.

RealmChangeListener для RealmObject теперь также будет запускаться при удалении объекта. Используйте RealmObject.isValid(), чтобы проверить это состояние (#3138). RealmObject.asObservable() теперь будет излучать объект при его удалении. Используйте RealmObject.isValid(), чтобы проверить это состояние (# 3138).

Удалены устаревшие классы Logger и AndroidLogger (#4050).

Благодаря интеграции результатов Realm ObjectStore, RealmResults снова в транзакциях, как в 0.88.3 и ранее.

Так simple for loops (индексация с for(int i = 0; ...) склонен к поломке - это означает, что вам нужно либо выполнить итерацию в обратном порядке, либо сначала создать коллекцию снимков.

OrderedRealmCollection<Thing> snapshot = results.createSnapshot();
for(int i = 0; i < snapshot.size(); i++) { ...

Также, RealmObject изменение слушателя теперь также будет выдавать при удалении, вам нужно проверить isValid() в слушателе изменений. Это сделано для того, чтобы вы могли обновить пользовательский интерфейс, если объект был удален в фоновом режиме.

3.1.0:

Обновлен формат файлов Realm. Существующие файлы Realm будут автоматически перенесены в новый формат при их открытии, но более старые версии Realm не могут открыть эти файлы.

Здесь делать нечего, но стоит упомянуть.

3.2.0-3.2.1:

Здесь нечего делать, кроме обновления Proguard, потому что здесь была введена ошибка. Добавлен раздел proguard.

3.3.0: (и 3.3.1)

Ничего не поделаешь, ошибка была исправлена, что вызвало проблему с Proguard в 3.2.0.

3.4.0:

Здесь делать нечего, хотя стоит посмотреть на новое @LinkingObjects API для обратных отношений.

На самом деле, рекомендуется заменить двунаправленные ссылки однонаправленными ссылками + обратные отношения.

3.5.0:

Ломать перемены

IllegalStateException будет брошено, если данный RealmModule не включает все необходимые классы модели (#3398).

Если вы не указали все объекты RealmObject в modules() (в случае, если вы используете несколько модулей вместо стандартных, например, RealmObjects из проекта библиотеки), вам необходимо убедиться, что вы фактически предоставляете все RealmObjects, которые являются частью схемы в ваших модулях.

Раньше он молча добавлял их, даже если их не было в модулях, но сейчас это не так.

4.0.0:

Ломать перемены

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

[ObjectServer] Обновлена ​​версия протокола до 22, которая совместима только с Realm Object Server> = 2.0.0.

[ObjectServer] Удалены устаревшие API-интерфейсы SyncUser.retrieveUser() и SyncUser.retrieveUserAsync(). Используйте взамен SyncUser.retrieveInfoForUser() и retrieveInfoForUserAsync().

[ObjectServer] SyncUser.Callback теперь принимает универсальный параметр, указывающий тип объекта, возвращаемого при вызове onSuccess.

[ObjectServer] Переименован в SyncUser.getAccessToken в SyncUser.getRefreshToken.

[ObjectServer] Удален устаревший API SyncUser.getManagementRealm().

Вызов Different () для отсортированного RealmResults больше не очищает определенную сортировку (#3503).

Расслабленная верхняя граница параметра типа RealmList, RealmQuery, RealmResults, RealmCollection, OrderedRealmCollection и OrderedRealmCollectionSnapshot.

Realm обновил свою поддержку RxJava1 до RxJava2 (#3497). Realm.asObservable() был переименован в Realm.asFlowable(). RealmList.asObservable() был переименован в RealmList.asFlowable(). RealmResults.asObservable() был переименован в RealmResults.asFlowable(). RealmObject.asObservable() был переименован в RealmObject.asFlowable(). RxObservableFactory теперь возвращает типы RxJava2 вместо типов RxJava1.

Удалены устаревшие API-интерфейсы RealmSchema.close() и RealmObjectSchema.close(). Их больше не нужно называть.

Удален устаревший API RealmResults.removeChangeListeners(). Вместо этого используйте RealmResults.removeAllChangeListeners().

Удален устаревший API RealmObject.removeChangeListeners(). Вместо этого используйте RealmObject.removeAllChangeListeners().

Удалены UNSUPPORTED_TABLE, UNSUPPORTED_MIXED и UNSUPPORTED_DATE из RealmFieldType.

Удален устаревший API RealmResults.distinct()/RealmResults.distinctAsync(). Используйте взамен RealmQuery.distinct()/RealmQuery.distinctAsync().

RealmQuery.createQuery (Realm, Class), RealmQuery.createDynamicQuery (DynamicRealm, String), RealmQuery.createQueryFromResult (RealmResults) и RealmQuery.createQueryFromList(RealmList) были удалены. Используйте взамен Realm.where(Class), DynamicRealm.where(String), RealmResults.where() и RealmList.where().

Таким образом, поддержка Rx1 была заменена поддержкой Rx2, и removeChangeListeners() был переименован в removeAllChangeListeners(),

Большинство других вещей влияют только на синхронизируемые области, и с этого момента можно использовать RealmList<String>, RealmList<Date>, а также RealmList<Integer> как часть схемы Realm. Запросы к ним пока не поддерживаются, и они не заполняются create*FromJson методы.

4.3.1:

Устаревшие

Варианты RealmQuery.findAllSorted() и RealmQuery.findAllSortedAsync() в пользу предиката RealmQuery.sort(). FindAll().

Варианты RealmQuery.distinct () и RealmQuery.distinctAsync() в пользу предиката RealmQuery.distinctValues ​​(). FindAll ()

Вместо того, чтобы использовать realm.where(Blah.class).distinct("something") или же realm.where(Blah.class).findAllSorted("something") Теперь вы можете сделать

realm.where(Blah.class)
     .distinctValues("something") // subject to change to `distinct()` 
     .sort("something") // hopefully will change to `sorted()`? // nope, it's `sort`
     .findAll();

5.0.0:

Переименован в RealmQuery.distinctValues ​​() в RealmQuery.distinct ()

Удалены ранее устаревшие RealmQuery.findAllSorted(), RealmQuery.findAllSortedAsync() RealmQuery.distinct() и RealmQuery.distinctAsync()`.

Параметр OrderedCollectionChangeSet в OrderedRealmCollectionChangeListener.onChange() больше не может иметь значение null. Используйте взамен changeSet.getState() (#5619).

Так что это означает, что realm.where(...).findAllSorted("field") должно быть realm.where(...).sort("field").findAll(),

Также приходит, что OrderedRealmCollectionChangeListener используется для отправки null в качестве первоначального набора изменений, теперь это уже не так, и == null следует заменить на .getState() == OrderedCollectionChangeSet.State.INITIAL, Это также означает, что вам нужно использовать realm-android-adapters 3.0.0 или новее с Realm 5.0+.

Кроме того, если вы полагались на имена __RealmProxy классы: они имеют полное имя, включая пакеты, например my_package_SomeObjectRealmProxy,


ПРАВИЛА ПРОГУРА

#realm older than 0.84.1
-keepnames public class * extends io.realm.RealmObject
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.** { *; }
-dontwarn javax.**
-dontwarn io.realm.**

#realm 0.84.1+ and older than 1.0.0
-keep class io.realm.annotations.RealmModule
-keep @io.realm.annotations.RealmModule class *
-keep class io.realm.internal.Keep
-keep @io.realm.internal.Keep class *
-dontwarn javax.**
-dontwarn io.realm.**

#realm 0.89.0+ and older than 1.0.0
-keep class io.realm.RealmCollection
-keep class io.realm.OrderedRealmCollection 

#realm 3.2.0 and 3.2.1
-keepnames public class * extends io.realm.RealmObject

Основное обновление до Realm от 4+ в 5+ необходимо изменить с:

realm.where(example.class)
    .findAllSorted("field")

Для того, чтобы:

realm.where(example.class)
    .sort("field")
    .findAll();
Другие вопросы по тегам