Adapter(适配器)
Realm提供了一些抽象的工具类来方便地将 OrderedRealmCollection (RealmResults 和 RealmList 都实现了这个借口)展示到UI控件上。
- RealmBaseAdapter 可以与 ListView 配合使用。参见示例.
- RealmRecyclerViewAdapter 可以与 RecyclerView 配合使用。参见示例. 你需要在 app 的 build.gradle 中添加额外的依赖以使用这些适配器。
1 | dependencies { |
Intent
因为你不可以直接通过 intent 传递 RealmObject,我们建议你只传递 RealmObject 的标识符。举个常用例子,假如你的对象拥有一个主键,请通过 intent 的 bundle 来传递这个主键的值。
1 | // Assuming we had a person class with a @PrimaryKey on the 'id' field ... |
在接受方(Activty、Service、IntentService、BroadcastReceiver 及其它)从 bundle 中解析出这个主键然后打开 Realm 查询得到这个 RealmObject。
1 | // in onCreate(), onHandleIntent(), etc. |
可以参考 threading example 中的 Object Passing 部分。该示例展示了在安卓开发中常用的如何传递 id 并且得到对应的 RealmObject。
Android Framework 多线程 API 相关
当你使用下列 API 时请小心:
- AsyncTask
- IntentService
AsyncTask 的 doInBackground() 方法会运行在一个后台线程。IntentService 的 onHandleIntent(Intent intent) 方法会运行在一个后台工作线程。
如果你需要在这些方法中使用 Realm,请在对 Realm 的调用结束后关闭 Realm 实例。见如下例子。
AsyncTask
在 doInBackground 方法中打开并关闭 Realm,如下所示:
1 | private class DownloadOrders extends AsyncTask<Void, Void, Long> { |
IntentService
ChangeListener 在 IntentService 中不会工作。尽管 IntentService 本身是一个 Looper 线程,但每次 onHandleIntent 的调用是独立的事件。你可以注册监听器的调用不会返回失败,但他们永远不会被触发。
在 onHandleIntent() 方法中打开并关闭 Realm,如下所示:
1 | public class OrdersIntentService extends IntentService { |
对其它库的支持
这个章节描述了怎样与其它 Android 流行库搭配使用 Realm。
GSON
GSON 是 Google 开发的 JSON 处理库。GSON 与 Realm 可以无缝配合使用。
1 | // Using the User class |
GridViewExample 展示了如何配合 GSON 使用 Realm。
序列化(Serialization)
你有时需要序列化与反序列化一个 Realm 对象以便与其它库(比如 Retrofit)相配合。因为 GSON使用成员变量值而非 getter 和 setter ,所以你无法通过 GSON 的一般方法来序列化 Realm 对象。
你需要为 Realm 模型对象自定义一个 JsonSerializer 并且将其注册为一个 TypeAdapter。
请参考这个 Gist。
数组(Primitive lists)
某些 JSON API 会以数组的形式返回原始数据类型(例如 String 和 integer),Realm 暂时不支持对这种数组的处理。但你可以通过自定义 TypeAdapter来处理这种情况。
这个 Gist 展示了如何将 JSON 中的整型数组存入 Realm。类似地,你可以用这个方法来处理其它原始数据类型数组。
Troubleshooting
Realm 对象属性可能会包含循环引用。在这种情况下,GSON 会抛出 StackOverflowError。例如如下 Realm 对象拥有一个 Drawable 属性:
1 | public class Person extends RealmObject { |
Person 类含有一个 Android Drawable 并且被 @Ignore 修饰。当 GSON 序列化时,Drawable 被读取并且造成了堆栈溢出。(GitHub Issue)。添加如下代码以避免类似问题:
1 | public boolean shouldSkipField(FieldAttributes f) { |
请注意对 Drawable.class 的判定语句,它告诉 GSON 跳过这个属性的序列化以避免堆栈溢出错误。
Jackson-databind
Jackson-databind 用来绑定 JSON 数据和其对应的 Java 类。
Jackson 需要使用反射进行工作。这与 Realm 的 RxJava 支持有冲突,因为作为可选功能,RxJava 有可能不再工程依赖库中。这会导致类似如下的异常抛出:
1 | java.lang.NoClassDefFoundError: rx.Observable |
为了修正这个问题你可以添加 RxJava 依赖到工程中或者创建一个假类文件如下所示:
package rx;
public class Observable {
// Dummy class required for Jackson-Databind support if
// RxJava is not a project dependency.
}
这个问题也同时报告给了 Jackson 项目。
Kotlin
Realm 完全兼容 Kotlin 语言,但有些地方需要注意:
- 你的模型类需要是开放的(open)。
- 你可能需要在某些情况下添加注解 @RealmCLass 以保证编译通过。这是由于当前 Kotlin 注解处理器的一个限制。
- 很多 Realm API 引用了 Java 类。你必须在编译依赖中添加 org.jetbrains.kotlin:kotlin-reflect:${kotlin_version}。
参见示例。
Parceler
Parceler 可以帮助对象自动生成支持 Parcelable 接口的样板代码。因为 Realm 的代理类,你需要以下设置以便应用 Parceler 到 Realm 对象。
1 |
|
如果你使用 Gradle 来获取 Parceler,请确保存在以下配置代码:
1 | compile "org.parceler:parceler-api:1.0.3" |
请注意目前在使用 Parceler 的时候有如下的限制:
- 如果你的模型包含 RealmList,那么你需要注册一个特殊 adapter
- 一旦对象被打包(parcelled),它将变为一个有当前数据快照,不再被 Realm 管理的一个 unmanaged 对象。之后该对象的数据变化不会被 Realm 写入。
Retrofit
Retrofit是一个由 Square 开发,保证类型安全(typesafe)的 REST API 处理工具。
Realm 可以与 Retrofit 1.x 和 2.x 无缝配合工作。但请注意 Retrofit 不会自动将对象存入 Realm。你需要通过调用 Realm.copyToRealm() 或 Realm.copyToRealmOrUpdate() 来将它们存入 Realm。
1 | GitHubService service = restAdapter.create(GitHubService.class); |
Robolectric
通过 Robolectric库可以让你在不使用真实设备或者模拟器的情况下直接在 Java 虚拟机上进行 JUnit 测试。但目前 Roboletrics 不支持带有原生库的测试。而 Realm 包含使用 C++ 的原生库,所以你目前不可以通过 Roboletrics 测试使用 Realm 的项目。
你可以关注这个 Robolectric 的新功能请求。
RxJava
RxJava 是 Netflix 发布的一个 [Reactive 的扩展 库以支持 观察者模式。
Realm 包含了对 RxJava 的原生支持。如下类可以被暴露为一个 Observable:Realm, RealmResults, RealmObject, DynamicRealm and DynamicRealmObject。
1 | // Combining Realm, Retrofit and RxJava (Using Retrolambda syntax for brevity) |
请注意异步查询不会阻塞当前线程,如上代码会立即返回一个 RealmResults 实例。如果你想确定该 RealmResults 已经加载完成请使用filter operator 和 RealmResults<E>.isLoaded() 方法。通过判断 RealmResults 是否已经加载可以得知查询是否已经完成。
配置
RxJava 是可选依赖,这意味着 Realm 不会自动包含它。这样做的好处是你可以选择需要的 RxJava 版本以及防止过多的无用方法被打包。如果你要使用相关功能,请手动添加 RxJava 到 build.gradle 文件。
1 | dependencies { |
你也可以通过继承 RxObservableFactory 来决定 Observable 的生成方式,然后通过 RealmConfiguration 进行配置。
1 | RealmConfiguration config = new RealmConfiguration.Builder() |
如果没有 RxObservableFactory 被定义,RealmObservableFactory 会被默认使用,它支持 RxJava <= 1.1.*。