2016-03-07 10 views
14

Utilizziamo Realm per la nostra app. La nostra app è stata rilasciata in versione beta. Ora voglio aggiungere un campo a uno dei nostri oggetti realm. Così ho scritto RealmMigration e ne ho scritto anche uno. La domanda qui è come applicare questa migrazione di Realm alla mia app. Io uso Realm.getInstance() ottenere l'istanza di regno ogni volta che voglio qualcosa. Ricorda che Realm.getInstance() viene utilizzato in ogni momento nell'intera app, desidero accedere al database di Realm.Il modo giusto di fare Migrazione del dominio Android

Quindi, mi è stato chiesto su come applicare questa migrazione? Qualsiasi vantaggio può essere utile. Grazie.

My RealmMigration è come segue.

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 e setter rimossi da RealmObject per interrompere la domanda. L'eccezione si è verificata quando provo a reinstallare l'app senza disinstallare quella precedente. Per favore consiglio

risposta

20

Viene descritto qui: https://realm.io/docs/java/latest/#migrations

Ma in sostanza, è sufficiente imbatterà la versione dello schema e impostare la configurazione in questo modo:

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(); 
+0

Grazie Christian. Se la mia comprensione è corretta, il modello avrà un campo appena creato e tutto il Realm.getInstance (this) sarebbe Realm.getInstance (config ) – User

+2

Sì, è corretto. Dovresti usare 'Realm.getDefaultInstance()' o 'Realm.getInstance (RealmConfiguration)' invece di 'Realm.getInstance (Context)'. –

+0

Oggi ho provato, sto ottenendo "io.realm.exceptions.RealmMigrationNeededException: Field 'isSessionRecordingUploading' supporta valori null nel file di Realm esistente Utilizza il tipo di box corrispondente per il campo 'isSessionRecordingUploading' o esegui la migrazione usando io.realm.internal.Table .convertColumnToNotNullable() ". Ho modificato la classe RealmMigration e aggiunto l'annotazione notNull al campo nel mio Realm Object. Ma ancora non ho potuto superare il problema. Ho aggiornato la Q. – User

0

Questa è una classe di supporto ho fatto per importare un. realm database alla mia applicazione. Nel mio caso ho solo bisogno di leggere il db creato da un'applicazione iOS in un'applicazione 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{ 
} 
} 

Se si dispone di più di una configurazione di regno (se avete bisogno di importare più di un file .realm) è necessario crea una classe RealmModule e usa l'opzione .modules() su RealmConfiguration.Builder.

Ciò è necessario perché per settore predefinito di cercare di controllare se il vostro .realm ha tavoli per tutti i modelli che si estendono RealmObject, e se si dispone di .realm multipla, ognuno di loro avrà alcune delle vostre classi (ma non tutti di loro).

Un'altra informazione utile è quella per le migrazioni da veloce a Android. Tutte le proprietà String devono essere dichiarate con l'anototazione @Required (se hanno un valore predefinito).

Se realm ti dà una strana eccezione come "questa classe non è stata trovata in questo schema", prova a eseguire nuovamente l'app, di solito dà un errore diverso che può suggerire il vero problema anche se a volte dà solo un errore casuale.

+0

è ['RealmConfiguration.assetFile()'] (https://realm.io/docs/java/latest/api/io/realm/RealmConfiguration.Builder.html#assetFile-java.lang.String-) troppo mainstream? Inoltre, non ci sono "errori casuali", probabilmente dovresti disabilitare l'esecuzione istantanea. – EpicPandaForce

+0

Ciao, sto solo cercando di aiutare gli altri utenti. Sentiti libero di modificare il mio codice con le tue preferenze. E anche disattivato Instant Run, ho ancora incontrato errori casuali come "questa tabella/classe non esiste" anche quando sono sicuro che il file e la tabella esista e finisce che l'errore è dovuto al "modulo". – sagits

+0

Sto solo dicendo che Realm ha già 'assetFile()', quindi non devi scrivere manualmente la copia: P – EpicPandaForce

Problemi correlati