2016-03-07 91 views
14

我們使用Realm作爲我們的應用程序。我們的應用已經發布。現在我想添加一個字段給我們的一個領域對象。所以我寫了RealmMigration,我也寫了一個。這裏的問題是如何將這個Realm遷移應用到我的應用程序。我使用Realm.getInstance()獲取領域實例,只要我想要的東西。請記住,Realm.getInstance()每次都在整個應用程序中使用,我想訪問Realm數據庫。做Realm遷移的正確方法Android

所以,我有點疑問如何應用此遷移?任何潛在客戶都可能會有幫謝謝。

我的RealmMigration如下。

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; 

} 

從RealmObject中刪除了Getter和Setter以縮短問題。當我嘗試重新安裝應用程序而未卸載前一個應用程序時發生異常。請指教。

回答

20

在此描述:https://realm.io/docs/java/latest/#migrations

但在本質上,你剛纔碰到的架構版本,並且設置配置是這樣的:

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

感謝Christian。如果我的理解是正確的,模型將有新創建的字段,並且所有Realm.getInstance(this)將是Realm.getInstance(config <像上面那樣創建>) – User

+2

是的,這是正確的。您應該使用'Realm.getDefaultInstance()'或'Realm.getInstance(RealmConfiguration)'而不是'Realm.getInstance(Context)'。 –

+0

今天我嘗試了,我得到了「io.realm.exceptions.RealmMigrationNeededException:Field'isSessionRecordingUploading'在現有的Realm文件中支持空值。使用相應的盒裝類型作爲字段'isSessionRecordingUploading'或使用io.realm.internal.Table .convertColumnToNotNullable()「。我稍微修改了RealmMigration類,並在Realm對象的字段中添加了notNull註釋。但我仍然無法克服這個問題。我更新了Q. – User

0

這是一個輔助類我已經導入。領域數據庫到我的應用程序。在我來說,我只需要讀取從iOS應用程序創建的數據庫中的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{ 
} 
} 

如果你有一個以上的領域配置(如果需要導入多個.realm文件),你需要創建一個RealmModule類並使用RealmConfiguration.Builder上的.modules()選項。

這是需要的,因爲默認情況下,realm會嘗試檢查.realm是否有擴展RealmObject的所有模型的表,並且如果您有多個.realm,它們中的每一個都會有一些類(但不是全部)。

另一個有用的信息是,迅速到Android的遷移。所有的字符串屬性必須用@Required anototation聲明(如果它們有默認值)。

如果領域給你一個奇怪的異常像「這個類沒有在這個模式中找到」,嘗試重新運行你的應用程序,通常它給出了一個不同的錯誤,可以暗示真正的問題,雖然有時它只是給出隨機錯誤。

+0

[[RealmConfiguration.assetFile()'](https://realm.io/docs/java/latest/api/io/realm/RealmConfiguration.Builder.html#assetFile-java.lang.String-)太主流了?此外,沒有「隨機錯誤」,你應該禁用即時運行。 – EpicPandaForce

+0

嗨,我只是想幫助其他用戶。隨意與您的sugestions編輯我的代碼。即使在確定文件和表存在時,我仍然遇到了像「這個表/類不存在」這樣的隨機錯誤,並且最終導致錯誤是因爲「模塊」。 – sagits

+0

我只是說Realm已經有了'assetFile()',所以你不必手動編寫複製:P – EpicPandaForce