Docs 菜单

Docs 主页开发应用程序Atlas Device SDKs

使用 Realm 文件 — .NET SDK

在此页面上

  • Realm 生命周期
  • 多进程
  • Realm 模式
  • 同步 Realm
  • 查找您的 Realm 文件
  • Realm 文件大小
  • 限制活动版本的最大数量
  • 压缩 Realm
  • 备份和恢复 Realm
  • 模块

Realm是一组符合预定义模式的相关对象。 Realm 可以包含多种类型的数据,只要每种类型都存在模式。

每个 Realm 都将数据存储在单独的 Realm 文件中,该文件包含 Realm 中每个对象的二进制编码。您可以跨多个设备自动同步 Realm,并设置响应式事件处理程序,以便在每次创建、修改或删除 Realm 中的对象时调用函数。

每个 Realm 实例都会消耗大量资源。打开和关闭 Realm 都是昂贵的操作,但保持 Realm 处于打开状态也会产生大量资源开销。为了最大限度地提高应用程序的性能,您应该在任何给定时间最大限度地减少打开 Realm 的数量,并限制使用的打开和关闭操作的次数。

然而,打开一个 Realm 并不总是那么昂贵。如果 Realm 已在同一进程或线程中打开,则打开额外的实例所需的资源更少:

  • 如果未在同一进程中打开 Realm,则打开 Realm 的开销很高。

  • 如果 Realm 已在同一进程内的不同线程上打开,则打开 Realm 的成本较低,但仍然很重要。

  • 如果已在同一进程内的同一线程上打开 Realm,则打开该 Realm 只需最少的额外资源。

当您首次打开一个 Realm 时,Realm 会执行在该 Realm 中读取和写入数据所需的内存映射和模式验证。同一线程上该 Realm 的其他实例使用相同的底层资源。不同线程上该 Realm 的实例使用一些相同的底层资源。

当一个 Realm 的所有连接在一个线程中关闭时,Realm 会释放用于连接该 Realm 的线程资源。当进程中与某个 Realm 的所有连接都关闭时,Realm 会释放用于连接该 Realm 的所有资源。

作为最佳实践,我们建议将 Realm 实例生命周期与观察域的视图的生命周期绑定在一起。实例,考虑一个通过RecyclerView 显示RealmResults 数据的Fragment 。您可以:

  • Fragment.onCreateView()生命周期方法中打开一个包含该视图数据的单个 Realm。

  • Fragment.onDestroyView()生命周期方法中关闭同一 Realm。

注意

如果您的 Realm 特别大,则在Fragment.onCreateView()中获取 Realm 实例可能会短暂阻止渲染。如果在onCreateView()中打开您的 Realm 会导致性能问题,请考虑改为从Fragment.onStart()Fragment.onStop()管理该 Realm。

如果多个Fragment实例需要访问同一数据集,您可以在封闭的Activity中管理单个 Realm:

  • Activity.onCreate()生命周期方法中打开 Realm。

  • Activity.onDestroy()生命周期方法中关闭 Realm。

您无法从不同进程同时访问加密同步Realm。但是,本地 Realm 可以正常跨进程运行,因此您可以读取、写入多个 APK 和接收来自多个 APK 的通知。

Realm 模式是有效对象模式的列表,每个模式定义应用程序可以持久保存的对象类型。 Realm 中的所有对象都必须符合 Realm 模式。

默认情况下,SDK 会自动将项目中从RealmObject派生的所有类添加到 Realm 模式中。

客户端应用程序在打开 Realm 时提供 Realm 模式。如果 Realm 已包含数据,则 Realm 会验证每个现有对象,以确保为其类型提供了对象模式,并且满足模式中指定的所有约束。

例子

包含图书馆中图书基本数据的 Realm 可能会使用如下模式:

[
{
"type": "Library",
"properties": {
"address": "string",
"books": "Book[]"
}
},
{
"type": "Book",
"primaryKey": "isbn",
"properties": {
"isbn": "string",
"title": "string",
"author": "string",
"numberOwned": { "type": "int?", "default": 0 },
"numberLoaned": { "type": "int?", "default": 0 }
}
}
]

使用 Atlas Device Sync 的应用程序可以打开同步 Realm。

使用Flexible Sync时,可以通过订阅查询来自定义客户端应用程序同步的数据。这些查询在应用程序后端搜索数据,Flexible Sync Realm 同步与查询匹配的数据。客户端应用程序只能同步用户具有适当读取或读写权限来访问数据的数据。

当您使用 基于分区的同步 时,同步的 Realm 表示 Atlas 数据的分区。每个 Realm 对应于应用数据源中数据的一个子集。您可以使用应用程序的 分区键 自定义数据 分区 。分区键的唯一值(称为 分区值 )与各个 Realm 相对应。

在配置Realm 规则时,您可以自定义同步 Realm 可以从您的应用程序读取和写入的数据的权限。

有关更多信息,请参阅配置同步 Realm - Java SDK。

Realm 将 Realm 中每个对象和类型的二进制编码版本存储在单个.realm文件中。

运行 Realm Studio 的机器无法直接访问 Android 模拟器使用的文件系统。您必须先从模拟器下载该文件,然后才能访问。

首先,在模拟器上找到该文件的路径:

// Run this on the device to find the path on the emulator
Realm realm = Realm.getDefaultInstance();
Log.i("Realm", realm.getPath());

然后,使用 ADB 下载文件。您可以在应用运行时执行此操作。

> adb pull <path>

您还可以使用 ADB 再次上传修改后的文件,但前提是应用未运行。在应用运行时上传修改后的文件可能会损坏该文件。

> adb push <file> <path>

提示

另请参阅:辅助 Realm 文件

Realm 会为每个 Realm 创建附加文件。要了解有关这些文件的更多信息,请参阅Realm 内部。

通常,与同等的 SQLite 数据库相比,Realm 在磁盘上占用的空间更少。但是,为了向您提供一致的数据视图,Realm 可对 Realm 的多个版本进行操作。如果同时打开某个 Realm 的多个版本,则该 Realm 文件可能需要额外的磁盘空间。

这些版本占用的空间量取决于每个事务中的更改量。许多小型事务的开销与少量大型事务相同。

文件大小意外增长通常由以下三个原因之一造成:

  1. 您在后台线程上打开一个 Realm,却忘记再次将其关闭。因此,Realm 在后台线程上保留了对旧版本数据的引用。由于 Realm 会在带有 Looper 的线程上自动将 Realm 更新到最新版本,因此 UI 线程和其他 Looper 线程不存在此问题。

  2. 您持有对太多版本的冻结对象的引用。冻结对象会保留首次冻结对象时存在的 Realm 版本。如果您需要冻结大量对象,请考虑使用Realm.copyFromRealm()来仅保留所需的数据。

  3. 您从 Realm 中读取了一些数据。然后,您可以通过长时间运行的操作来阻止线程。同时,您在其他线程上多次向 Realm 写入。这会导致 Realm 创建许多中间版本。您可以通过以下方式避免这种情况:

    • 批处理写入

    • 避免让 Realm 保持打开状态,否则会阻塞后台线程。

您可以在构建RealmConfiguration时设置maxNumberOfActiveVersions() ,以便在应用程序打开的 Realm 版本超过允许数量时引发IllegalStateException 。版本是在执行写事务时创建的。

一旦应用程序不再使用旧版本的数据,Realm 会自动删除这些数据。但是,Realm 不会释放旧版本数据所使用的空间;相反,该空间用于对 Realm 进行新的写入。

您可以通过压缩Realm 文件来删除未使用的空间:

重要

压缩所有生产应用程序

每个生产应用程序都应实施压缩,以定期减小 Realm 文件的大小。

Realm 使用 Android 设备上的文件将 Realm 持久保存到磁盘。要备份 Realm,请找到 Realm 文件并将其复制到安全位置。您应该在复制 Realm 之前关闭该 Realm 的所有实例。

或者,也可以使用realm.writeCopyTo()将 Realm 的压缩版本写入目标文件。

提示

另请参阅:

如果要将 Realm 备份到外部位置(例如 Google 云端硬盘),请参阅以下文章系列:( 第1 部分 , 第2 部分3 , 第 部分 )。

Realm 模块描述了可以存储在 Realm 中的一组 Realm 对象。默认情况下,Realm 会自动创建一个 Realm 模块,其中包含应用程序中定义的所有 Realm 对象。您可以定义RealmModule ,将 Realm 限制为应用程序中定义的类的子集。如果您生成一个使用 Realm 的库,则可以使用 Realm 模块来显式仅将库中定义的 Realm 对象包含在您的 Realm 中。这样,包含您的库的应用程序也可以使用 Realm,而无需管理与您的库定义的 Realm 对象的对象名称冲突和迁移。

← LiveData 快速入门 - Java SDK