Правильный способ осуществления Realm Migration Android
Мы используем Realm для нашего приложения. Наше приложение было выпущено в бета-версии. Теперь я хочу добавить поле в один из наших объектов области. Поэтому я должен написать RealmMigration, и я тоже написал. Вопрос здесь в том, как применить эту миграцию Realm к моему приложению. Я использую Realm.getInstance(), чтобы получить экземпляр области, когда захочу. Помните, Realm.getInstance() используется во всем приложении каждый раз, я хочу получить доступ к базе данных Realm.
Итак, я немного спросил, как применить эту миграцию? Любые выводы могут быть полезны. Спасибо.
My RealmMigration выглядит следующим образом.
public class RealmMigrationClass implements RealmMigration {
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
if(oldVersion == 0) {
RealmSchema sessionSchema = realm.getSchema();
if(oldVersion == 0) {
RealmObjectSchema sessionObjSchema = sessionSchema.get("Session");
sessionObjSchema.addField("isSessionRecordingUploading", boolean.class, FieldAttribute.REQUIRED)
.transform(new RealmObjectSchema.Function() {
@Override
public void apply(DynamicRealmObject obj) {
obj.set("isSessionRecordingUploading", false);
}
});
sessionObjSchema.setNullable("isSessionRecordingUploading",false);
oldVersion++;
}
}
}
}
public class Session extends RealmObject {
@PrimaryKey
private String id;
@Required
private Date date;
private double latitude;
private double longitude;
private String location;
private String note;
private String appVersion;
private String appType;
private String deviceModel;
private HeartRecording heart;
private TemperatureRecording temperature;
private LungsRecording lungs;
@NotNull
private boolean isSessionRecordingUploading;
private boolean sessionInfoUploaded;
private boolean lungsRecordingUploaded;
private boolean heartRecordingUploaded;
}
Убрал Getter и Setters из RealmObject, чтобы прервать вопрос. Исключение произошло, когда я пытаюсь переустановить приложение, не удаляя предыдущий. Пожалуйста, совет.
Ответы
Ответ 1
Здесь описано: https://realm.io/docs/java/latest/#migrations
Но в сущности, вы просто набросаете версию схемы и задаете конфигурацию следующим образом:
RealmConfiguration config = new RealmConfiguration.Builder(context)
.schemaVersion(2) // Must be bumped when the schema changes
.migration(new MyMigration()) // Migration to run
.build();
Realm.setDefaultConfiguration(config);
// This will automatically trigger the migration if needed
Realm realm = Realm.getDefaultInstance();
Ответ 2
Это вспомогательный класс, который я сделал для импорта базы данных .realm в мое приложение. В моем случае мне просто нужно прочитать db, созданный из приложения iOS в приложении для Android.
public class RealmImporter {
private Activity activity;
private String dbaFullName = "db.realm";
private int rawRealmResource = R.raw.dbRealmResource;
public RealmImporter (Activity activity) {
this.activity = activity;
importData();
}
private RealmConfiguration getConfiguration() {
RealmConfiguration config = new RealmConfiguration.Builder()
.name(dbaFullName)
.modules(new MyRealmModule())
.migration(new RealmMigration() {
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
}
})
.build();
return config;
}
public Realm getInstance() {
Realm realm = Realm.getInstance(getConfiguration());
return realm;
}
private void importData() {
copyBundledRealmFile(activity.getResources().openRawResource(rawRealmResource), dbaFullName);
Realm.init(activity);
}
private String copyBundledRealmFile(InputStream inputStream, String outFileName) {
try {
File file = new File(activity.getFilesDir(), outFileName);
if (file.exists()) {
return file.getAbsolutePath();
}
FileOutputStream outputStream = new FileOutputStream(file);
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, bytesRead);
}
outputStream.close();
return file.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// Create the module
@RealmModule(classes = { Artigo.class, Comparativo.class, Indice.class, ItemDeArtigo.class})
public static class MyRealmModule{
}
}
Если у вас более одной конфигурации (если вам нужно импортировать более одного файла .realm), вам нужно создать класс RealmModule и использовать параметр .modules() в RealmConfiguration.Builder.
Это необходимо, потому что по умолчанию realm попытается проверить, имеют ли ваши .realm таблицы для всех ваших моделей, которые расширяют RealmObject, и если у вас есть несколько .realm, каждый из них будет иметь некоторые из ваших классов (но не все их).
Другая полезная информация заключается в том, что для быстрой миграции android. Все свойства String должны быть объявлены с помощью @Required anototation (если они имеют значение по умолчанию).
Если realm дает вам странное исключение, например, "этот класс не был найден в этой схеме", попробуйте повторно запустить приложение, обычно оно дает другую ошибку, которая может намекать на реальную проблему, хотя иногда она просто дает случайную ошибка.