Appearance
看 Realm 的文档,为了避免需要时再去整篇文档搜寻一番,在这里做一些记录。
修饰符
@Required 不能为空的字段
@Ignore 不会被保存到 Realm 的字段
@Index 为字段添加索引,写入变慢、文件体积增加
@PrimaryKey 主键
自动更新
RealmObject
和 RealmResults
在数据库变动的时候会自动更新,可通过 addChangeListener()
监听事件。
只有托管对象才有自动更新功能,原始对象并没有!!
为避免在遍历列表时被自动更新影响,可以通过 createSnapshot
创建快照。
主键
Realm.createObject()
会返回一个字段都是默认值的对象,包括主键,所以建议先创建一个非托管对象设置主键然后调用 copyToRealmOrUpdate()
创建托管对象。
声明 Realm 数据模型
继承 RealmObject
实现 RealmModel
接口
关系
RealmObject
之间的关联并不会消耗太多系统开销。
可以使用 RealmList
实现多对多关系,甚至是递归关系。其 getter()
永远返回一个 RealmList
对象。
关联查询
java
realm.where(Person.class).equalTo("dogs.color", "Brown").findAll()
.equalTo("dogs.age", 1).findAll(); // 在上面的查询结果下继续查
事务
读取事务是隐式的,写入事务是显式的,所有写操作都必须包含在事务内。
事务可以取消,事务之间会阻塞,所以避免在 UI 线程和后台线程同时使用写入事务。
读取事务不会被写入事务阻塞,并且在写入事务完成后会自动刷新没个 Realm 对象。所以,推荐使用一个大的写入事务而不是多个小的写入事务。
异步事务
java
RealmAsyncTask realmAsyncTask = realm.executeTransactionAsync(写入操作,成功回调,错误回调);
回调函数是通过 Looper 被执行的,在非 Looper 线程中只能传入 null.
在退出时应检查 realmAsyncTask
是否已被取消,从而避免 crash.
查询
Realm 中的所有读取(包括查询)操作都是延迟执行的,且数据绝不会被拷贝。
删除对象时,为避免在迭代时崩溃,应选用 realmList.deleteFromRealm(index)
而不是 realm.deleteFromRealm()
。
一般情况下可以直接在 UI 线程进行查询操作,但在涉及非常复杂的操作或大量数据的时候也可以选用异步查询,findAllAsync()
会在后台获取数据之后更新之前返回的 RealmResults
对象,可以使用 result.isLoaded()
检查是否完成。
Realms
在调用 Realm 实例之前,需要且只需要调用一次 Realm.init(ctx)
方法初始化。之前可通过 Realm.getInstance(ctx)
获取 Realm 实例,同一个线程同一个数据库文件会返回同一个实例。
关闭 Realm 实例
在使用完毕之后请务必关闭实例,以释放 native 内存和文件描述符。
由于 Realm 实例是基于引用计数的,所以调用多少次 getInstance()
就需要关闭多少次。
JSON
可以通过 Realm.createOjbectFromJson()
和 Realm.createAllFromJson()
将 JSON 对象直接添加到 Realm 中,包括 String、JSONObject、InputStream。
通知
RealmChangeListener
在任何数据发生变化的时候触发。
OrderedRealmCollectionChangeListener
在集合发生变化的时候触发,参数包含增删改的范围。
RealmObjectChangeListener
在对象发生变化时触发,参数包含改变的字段。
懒加载
Realm 跳过了整个拷贝过程,因为数据库文件是 memory-mapped。Realm 只需要简单计算偏移来找到文件中的数据,然后从原始访问点返回数据结构。
Looper
在线程中通过 Looper.prepare()
为线程设定一个唯一的 Looper
,用于轮循处理由 Handler 发来的消息。
kotlin
private val mHandler = Handler(Handler.Callback { msg: Message ->
when (msg.what) {
SCAN_OK -> true
else -> false
}
})