web-dev-qa-db-fra.com

Bonne façon de faire la migration de domaine Android

Nous utilisons Realm pour notre application. Notre application a été publiée en version bêta. Maintenant, je veux ajouter un champ à l'un de nos objets de domaine. J'ai donc dû écrire RealmMigration et j'en ai aussi écrit un. La question ici est de savoir comment appliquer cette migration de domaine à mon application. J'utilise Realm.getInstance () pour obtenir l'instance de domaine chaque fois que je veux quelque chose. N'oubliez pas que Realm.getInstance () est utilisé à chaque fois dans l'application entière, je souhaite accéder à la base de données Realm.

Donc, je suis un peu interrogé sur la façon d'appliquer cette migration? Toutes les pistes peuvent être utiles. Merci.

Ma RealmMigration est la suivante.

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 et Setters supprimés de RealmObject pour couper court à la question. L'exception s'est produite lorsque j'essaie de réinstaller l'application sans désinstaller la précédente. Veuillez conseiller.

20
User

Il est décrit ici: https://realm.io/docs/Java/latest/#migrations

Mais en substance, vous venez de bump la version du schéma et définissez la configuration comme ceci:

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();
29

Il s'agit d'une classe d'aide que j'ai créée pour importer une base de données .realm dans mon application. Dans mon cas, j'ai juste besoin de lire la base de données créée à partir d'une application iOS dans une application 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{
}
}

Si vous avez plusieurs configurations de domaine (si vous devez importer plusieurs fichiers .realm), vous devez créer une classe RealmModule et utiliser l'option .modules () sur RealmConfiguration.Builder.

Cela est nécessaire car par défaut, le domaine essaie de vérifier si votre .realm a des tables pour tous vos modèles qui étendent RealmObject, et si vous avez plusieurs .realm, chacun d'eux aura certaines de vos classes (mais pas toutes).

Une autre information utile est que pour Swift to Android. Toutes les propriétés de chaîne doivent être déclarées avec @Required anototation (si elles ont une valeur par défaut).

Si le domaine vous donne une étrange exception comme "cette classe n'a pas été trouvée dans ce schéma", essayez de relancer votre application, généralement cela donne une erreur différente qui peut faire allusion au vrai problème bien que parfois cela donne juste une erreur aléatoire.

0
sagits