So we have a scenario where a user has version 1.0 of an app. Version 2.0 comes out, but the user does not update. When version 3.0 comes out, the user decides to update.
Because the user has not updated the app, the realm file has not been updated either, so while doing migration from version 1.0 to version 3.0 the version
parameter of Migration.execute
will have the value 1 instead of 2.
There are also issues when the user installs directly version 2.0 of the app and then migrates to version 3.0. The same as in the previous case, the version
parameter will be wrong.
Is there a way to properly handle these cases?
Realm is a cross-platform mobile database solution designed for mobile applications. It's fast, lightweight, and quite simple to integrate into your project. Furthermore, it doesn't rely on Core Data or a SQLite database.
To migrate the realm to conform to the updated Person schema, the developer sets the realm's schema version to 2 and defines a migration function to set the value of fullName based on the existing firstName and lastName properties.
Actually Realm's migration example shows this scenario.
public class Migration implements RealmMigration {
@Override
public long execute(Realm realm, long version) {
// Step 0
if (version == 0) {
//Do the migration from 0 to 1
version++;
}
// Step 1
// Now the version is at least 1
if (version == 1) {
// Do the migration from 1 to 2
version++;
}
// Step 2
if (version == 2) {
// Do the migration from 2 to 3
version++;
}
// Now you get your final version 3
return version;
}
}
Simply just write the migration step by step, run them one by one until you get the latest schema version. For in your case, the user might have a Realm db version 0 here, and the step0 will run first. Then the version bump to 1 in the step 0 block, and the step 1 will run then.
------------ Update for user install version 3 directly case ------------
When create the realm instance, the code would be like:
RealmConfiguration config = new RealmConfiguration.Builder(this)
.migration(migration)
.schemaVersion(3)
.build();
Realm realm = Realm.getInstance(config);
Please notice that the schemaVersion(3)
here.
The RealmMigration.execute()
will only be executed if a migration is needed. This means if user install version 3 directly without having any previous version installed on the device, the RealmMigration.execute()
won't be called and the after the Realm file initialized, the schema version will be set to 3.
I'm not the Realm
guru and I haven't used Realm
in the real projects, but this approach should work:
Let's assume that you use this migration example:
You need an additional property saved in the project (in SharedPreferences
for instance) - latestMigrationVersion
. By default, latestMigrationVersion = 0
, which means we didn't run migrations yet.
Modify you Migration.java
class in the following way:
@Override
public long execute(Realm realm, long version) {
// check if the previous migration took place
if (version > 0 && version - 1 > latestMigrationVersion) {
// user missed migration
// then we need to run previous missed migrations before
version = latestMigrationVersion;
}
// do migrations as described in the example.
...
// update latestMigrationVersion for future checks
latestMigrationVersion = version;
// save the property locally
}
Now, if the user directly installs the 2.0 version, all previous migrations will be executed, before 2.0 -> 3.0
migration.
Unit tests
should help you to check all possible migrations: 0.0 -> 3.0
, 1.0 -> 2.0
, 2.0 -> 3.0
, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With