【问题标题】:Realm with pre populated data into assets?将数据预先填充到资产中的领域?
【发布时间】:2015-11-12 15:23:21
【问题描述】:

通常我将 Realm 用作:

RealmConfiguration config = new RealmConfiguration.Builder(applicationContext).deleteRealmIfMigrationNeeded().build();

如何在我的项目的 assets 文件夹中添加一个包含数据的数据库并读取它?

【问题讨论】:

    标签: android realm


    【解决方案1】:

    自 Realm Java 0.91.0 以来,RealmConfiguration 上有一个 assetFile(String) 选项,它会自动从资产中复制一个文件并在需要时使用它(例如,如果 Realm 第一次打开或已被删除某种原因):

    RealmConfiguration config = new RealmConfiguration.Builder()
      .assetFile("path/to/file/in/assets") // e.g "default.realm" or "lib/data.realm"
      .deleteRealmIfMigrationNeeded()
      .build()
    

    上述内容会在 Realm 首次打开或由于迁移而被删除时从资产中复制文件(在这种情况下请记住更新资产 Realm)。


    旧答案:

    可以在 assets 文件夹中捆绑 Realm 数据库,但您只需在第一次启动应用程序时从那里复制它。

    这里有一个如何复制文件的示例:https://github.com/realm/realm-java/blob/master/examples/migrationExample/src/main/java/io/realm/examples/realmmigrationexample/MigrationExampleActivity.java#L101-Lundefined

    copyBundledRealmFile(this.getResources().openRawResource(R.raw.default_realm), "default.realm");
    
    private String copyBundledRealmFile(InputStream inputStream, String outFileName) {
        try {
            File file = new File(this.getFilesDir(), outFileName);
            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 (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    

    【讨论】:

    • 也许 this 应该更新为使用 assetFile()
    • 好主意。完成。
    • 很高兴看到assetFile() 添加了!对于 Realm 以只读方式使用的场景(例如产品目录场景),最好有一个“仅在较新时复制”选项。这避免了不必要的复制,但简化了事情。 (我很想退休:github.com/eggheadgames/android-realm-asset-helper!)
    【解决方案2】:

    由于 Realm 0.89.0 RealmConfiguration.initialData(Realm.Transaction) 现在可以在第一次使用之前填充 Realm 文件。

    RealmConfiguration conf = new RealmConfiguration.Builder(context)
    .initialData(new Realm.Transaction() {
                    @Override
                    public void execute(Realm realm) {
                      realm.beginTransaction();
                      realm.createObject(....)
                      realm.commitTransaction();
                    }
                }).deleteRealmIfMigrationNeeded().name("mRealm.db").build();
    Realm realm = Realm.getInstance(conf);
    

    【讨论】:

      【解决方案3】:

      [编辑]见下面斯坦的回答。显然 Realm 现在直接支持这个,所以你可以忽略这个答案(除非你使用的是旧的 Realm 版本)。

      我们有类似的需求,并且还希望支持与 iOS 版本的应用共享的只读领域数据库。

      我们创建了一个简单的库并将其开源。它包括@christian-melchior 的答案中给出的复制代码,以及与 APK 捆绑的只读领域数据库的一些可选额外跟踪。欢迎评论和 PR。见:

      https://github.com/eggheadgames/android-realm-asset-helper

      【讨论】:

      • 请给我们一个完整的项目代码来演示如何使用这个库
      • 这和 Kotlin 中的实现是一样的吗?
      【解决方案4】:

      Realm 在其RealmConfiguration.Builder 中有一个特殊的参数,称为assetFile。你可以像这样使用它:

      realmConfiguration = new RealmConfiguration.Builder()
                          .assetFile("dataBase/default.realm") // your app's packaged DB
                          ...
                          .build();
      

      只需设置您的资产数据库路径和文件名,您就可以不用任何 android-realm-asset-helper 库或 copy-file-from-assets 代码。在此示例中,我的应用打包的 DB 文件位于“assets/dataBase/default.realm”中。
      请注意,低于 2 的版本有另一种调用assetFile 的方式,您应该另外传递上下文:

      realmConfiguration = new RealmConfiguration.Builder(context)
              .assetFile(context, "dataBase/default.realm")
              .build();
      

      【讨论】:

      • 我应该将 RealmObject 类设置为与 Realm 文件中的表同名吗?如果我想给它起不同的名字怎么办?
      【解决方案5】:

      您可以使用assetFile() 方法。请注意,您不能将assetFile()deleteIfMigrationNeeded() 一起使用。

      【讨论】:

      • 我已经做到了,但这里的问题是它没有崩溃,或者当我使用assetFile() 方法时,我的查询将为空。就好像什么也没发生一样,问题就出在哪里。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 2017-02-28
      • 2017-08-10
      • 2022-08-17
      • 2013-03-08
      • 2021-06-30
      相关资源
      最近更新 更多