2016-03-07 59 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