Search code examples
androidrealm

I am getting Migration error whenever i am creating a new Realm class?


I have created a class that extends RealmObject and whenever i try to run the class i get runTime exception as follows:

06-09 00:58:16.333 30719-30719/com.khaalijeb.inkdrops E/AndroidRuntime: FATAL EXCEPTION: main Process: com.khaalijeb.inkdrops, PID: 30719 io.realm.exceptions.RealmMigrationNeededException: Migration is required due to the following errors: - Class 'transactionacknowledgedata' has been added. at io.realm.internal.OsSharedRealm.nativeGetSharedRealm(Native Method) at io.realm.internal.OsSharedRealm.(OsSharedRealm.java:171) at io.realm.internal.OsSharedRealm.getInstance(OsSharedRealm.java:241) at io.realm.BaseRealm.(BaseRealm.java:136) at io.realm.BaseRealm.(BaseRealm.java:105) at io.realm.Realm.(Realm.java:164) at io.realm.Realm.createInstance(Realm.java:435) at io.realm.RealmCache.doCreateRealmOrGetFromCache(RealmCache.java:342) at io.realm.RealmCache.createRealmOrGetFromCache(RealmCache.java:282) at io.realm.Realm.getDefaultInstance(Realm.java:343) at com.khaalijeb.inkdrops.Fragment.NewPendingFragment.onCreate(NewPendingFragment.java:147) at android.support.v4.app.Fragment.performCreate(Fragment.java:2236) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1285) at android.support.v4.app.FragmentTransition.addToFirstInLastOut(FragmentTransition.java:1085) at android.support.v4.app.FragmentTransition.calculateFragments(FragmentTransition.java:976) at android.support.v4.app.FragmentTransition.startTransitions(FragmentTransition.java:95) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2198) at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2155) at android.support.v4.app.FragmentManagerImpl.execSingleAction(FragmentManager.java:2034) at android.support.v4.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:626) at android.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:143) at android.support.v4.view.ViewPager.populate(ViewPager.java:1268) at android.support.v4.view.ViewPager.populate(ViewPager.java:1116) at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1642) at android.view.View.measure(View.java:23167) at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715) at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461) at android.view.View.measure(View.java:23167) at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:715) at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:461) at android.view.View.measure(View.java:23167) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:23167) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.support.v7.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:139) at android.view.View.measure(View.java:23167) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535) at android.widget.LinearLayout.measureVertical(LinearLayout.java:825) at android.widget.LinearLayout.onMeasure(LinearLayout.java:704) at android.view.View.measure(View.java:23167) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at android.view.View.measure(View.java:23167) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1535) at android.widget.LinearLayout.measureVertical(LinearLayout.java:825) at android.widget.LinearLayout.onMeasure(LinearLayout.java:704) at android.view.View.measure(View.java:23167) at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6749) at android.widget.FrameLayout.onMeasure(FrameLayout.java:185) at com.android.internal.policy.DecorView.onMeasure(DecorView.java:716) 06-09 00:58:16.334 30719-30719/com.khaalijeb.inkdrops E/AndroidRuntime: at android.view.View.measure(View.java:23167) at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2693) at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1559) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1830) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1447) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7130) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:935) at android.view.Choreographer.doCallbacks(Choreographer.java:747) at android.view.Choreographer.doFrame(Choreographer.java:682) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:921) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6642) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

i dont know why i am getting this error. Anyone out there faced this problem?


Solution

  • Remember when in SQLite you wanted to add a table, so you had to do this:

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        int currentVersion = oldVersion;
        if(currentVersion == 1) {
            db.execSql("CREATE TABLE Blah(personId int, name varchar(255))");
            currentVersion++;
        }
        ...
    }
    

    And so on?

    Well Realm is not SQLite, but it still needs you to modify the schema to add the new model classes and apply schema changes you want.

    So you need to define a Migration (see this whole section about it in the docs) that handles the schema version change from X to Y.


    So you create a migration:

    public class Migration implements RealmMigration {
    
        @Override
        public void migrate(final DynamicRealm realm, long oldVersion, long newVersion) {
            ...
        }
    
        @Override
        public int hashCode() { return Migration.class.hashCode(); }
    
        @Override
        public boolean equals(Object obj) { return obj != null && obj instanceof Migration; }
    }
    

    Bump the schema version and specify the migration to the RealmConfiguration

    Realm.setDefaultConfiguration(new RealmConfiguration.Builder()
                                        .schemaVersion(currentVersion+1) // probably a constant somewhere
                                        .migration(new Migration())
                                        .build());
    

    And you actually need to write the migration using the DynamicRealm API that adds the newly added class.

    @Override
    public void migrate(DynamicRealm realm, long oldVersion, long newVersion) {
        RealmSchema schema = realm.getSchema();
        if(oldVersion == 0) {
            RealmObjectSchema transactionacknowledgedata = 
                                   schema.create("transactionacknowledgedata");
            transactionacknowledgedata.addField("name", String.class);
            oldVersion++;
        }
    }
    


    Well it's either that, or you set new RealmConfiguration.Builder().deleteIfMigrationNeeded().build() and you'll delete (and recreate) the Realm whenever there is a model change.