Skip to content

Instantly share code, notes, and snippets.

@CDRussell
Created April 22, 2016 13:14
Show Gist options
  • Save CDRussell/9ba479f01288dd930eeec58a749fdf51 to your computer and use it in GitHub Desktop.
Save CDRussell/9ba479f01288dd930eeec58a749fdf51 to your computer and use it in GitHub Desktop.
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import io.realm.DynamicRealm;
import io.realm.RealmMigration;
import io.realm.RealmSchema;
import io.realm.exceptions.RealmMigrationNeededException;
/**
* This is only run when the Realm DB schema has changed or when
* {@value REALM_DB_SCHEMA_VERSION is updated
* <p>
* It is important to work from the provided old version code and not the new one to ensure all updates are applied.
* This ensures all intermediate updates are applied even if the user has skipped several versions
* of the app containing DB updates
*/
public class RealmDatabaseMigrator implements RealmMigration {
public static final int REALM_DB_SCHEMA_VERSION = 0;
private static final String TAG = RealmDatabaseMigrator.class.getSimpleName();
private List<RealmMigrationStep> migrationSteps = new ArrayList<>();
public RealmDatabaseMigrator() {
// place migration steps here
migrationSteps.add(new Version1Migrator());
}
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
Log.i(TAG, String.format(Locale.getDefault(), "Migrating from version %d to version %d", oldVersion, newVersion));
// Access the Realm schema in order to create, modify or delete classes and their fields.
RealmSchema schema = realm.getSchema();
if (newVersion == oldVersion) {
throwMigrationException(realm, "Realm DB version not incremented");
}
long migrationsNeeded = newVersion - oldVersion;
long stepsAvailable = migrationSteps.size() - oldVersion;
if (migrationsNeeded > stepsAvailable) {
String errorMessage = String.format(Locale.getDefault(), "%d migrations needed to get from version %d to version %d, %d provided",
migrationsNeeded, oldVersion, newVersion, stepsAvailable);
throwMigrationException(realm, errorMessage);
}
while (oldVersion < newVersion) {
Log.d(TAG, "Migrating from version " + oldVersion);
migrationSteps.get((int) oldVersion).migrate(schema);
oldVersion++;
}
Log.i(TAG, String.format(Locale.getDefault(), "Realm DB now at version %d", oldVersion));
}
private void throwMigrationException(DynamicRealm realm, String message) {
throw new RealmMigrationNeededException(realm.getPath(), message);
}
public static class Version1Migrator implements RealmMigrationStep {
@Override
public void migrate(RealmSchema schema) {
// add migration logic here
}
}
public interface RealmMigrationStep {
void migrate(RealmSchema schema);
}
}
@CDRussell
Copy link
Author

Whenever you need to make a change to Realm DB schema, simply:

  1. increment the REALM_DB_SCHEMA_VERSION by 1
  2. add your new migration step as indicated by // place migration steps here.

A RealmMigrationNeededException is thrown when the schema is changed or the DB version number is changed without having added the required migration steps for it.

It is useful to catch this exception during development and wipe the Realm DB.

catch (RealmMigrationNeededException e) {
    String errorMessage = "Realm DB Migration required and not handled.\nThis is only acceptable " +
        "during development whilst changing Realm schema.\n" +
        "RealmDatabaseMigrator must be updated to handle ANY new realm schema changes";
    Log.wtf(TAG, errorMessage, e);

    Realm.deleteRealm(getRealmConfiguration());
}

Provide your own means for getRealmConfiguration()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment