Realm 数据库快速上手

Android 供了多种选项来保存永久性应用数据。
- Shared preferences
 - Internal file storage
 - External file storage
 - Databases
 - Network
 
其中数据库存储是一种必备技能,而衍生的mobile db也是层出不穷,本节主要介绍全平台(除Android,iOS,macOS外还支持web,桌面应用)Realm数据库在Android上的使用
快速上手
- Android Studio 1.5.1+
 - JDK1.7+
 - Android API 9+
 - Realm 默认情况下使用内部存储(internal storage),一般来说,这个文件位于
/data/data/<packagename>/files/,文件名:default.realm 
集成
- 
在项目的 build.gradle 文件中添加如下 class path 依赖
1
2
3
4
5
6
7
8buildscript {
repositories {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:5.0.0"
}
} - 
在 app 的 build.gradle 文件中应用 realm-android 插件
1
apply plugin: 'realm-android'
 
初始化
- 
默认初始化
1
2
3
4
5
6
7
8public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
// 默认Realm的配置文件
Realm.init(this);
}
} - 
自定义初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class MyApplication extends Application {
public void onCreate() {
super.onCreate();
// 自定义配置Realm
initRealm();
}
private void initRealm() {
RealmConfiguration config = new RealmConfiguration.Builder()
.name("myrealm.realm") // 命名文件名:myrealm.realm
.inMemory() // 一个非持久化的、存在于内存中的 Realm 实例
.encryptionKey(getKey()) // 数据库加密key
.schemaVersion(2) // 数据库结构版本号
.modules(new MySchemaModule()) // 数据库结构对象
.migration(new MyMigration()) // 数据库迁移
.build();
Realm.setDefaultConfiguration(config);
}
}- Realm 实例是线程单例化的,也就是说多次在同一线程调用静态构建器会返回同一 Realm 实例
 - 使用同样的名称同时创建“内存中的”Realm 和常规的(持久化)Realm 是不允许的
 
 
字段类型
Realm 支持以下字段类型:boolean、byte、short、int、long、float、double、String、Date和byte []。整数类型 short、int 和 long 都被映射到 Realm 内的相同类型(实际上为 long )。
- @Required修饰类型和空值(null)
Realm强制禁止空值(null)被存储
只有Boolean,Byte,Short,Integer,Long,Float,Double,String,byte[],Date可被修饰 - @Ignore标识一个字段不应该被保存到 Realm
 - @Index为字段增加搜索索引
仅支持索引的属性类型包括:
String,byte,short,int,long,boolean和Date - @PrimaryKey
必须为字符串(
String)或整数(short,int,long)以及它们的包装类型(Short,Int,Long) 
声明Realm数据模型
RealmObject
可以把RealmObject 当作POJO使用
1  | public class User extends RealmObject {  | 
RealmModel
1  | 
  | 
关系
多对一
1  | public class Contact extends RealmObject {  | 
多对多
1  | public class Contact extends RealmObject {  | 
CRUD
- 所有的写操作(添加、修改和删除对象),必须包含在写入事务(transaction)中
 - 在提交期间,所有更改都将被写入磁盘,并且,只有当所有更改可以被持久化时,提交才会成功。通过取消一个写入事务,所有更改将被丢弃。
 - 益于 Realm 的 MVCC 架构,当正在进行一个写入事务时读取操作并不会被阻塞!这意味着,除非你需要从多个线程进行并发写入操作,否则,你可以尽量使用更大的写入事务来做更多的事情而不是使用多个更小的写入事务。
 
增
- 
事务执行
1
2
3
4
5
6
7
8
9Realm realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
public void execute(Realm realm) {
User user = realm.createObject(User.class);
user.setName("John");
user.setEmail("john@corporation.com");
}
}); - 
异步事务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19Realm realm = Realm.getDefaultInstance();
realm.executeTransactionAsync(new Realm.Transaction() {
public void execute(Realm bgRealm) {
User user = bgRealm.createObject(User.class);
user.setName("John");
user.setEmail("john@corporation.com");
}
}, new Realm.Transaction.OnSuccess() {
public void onSuccess() {
// Transaction was a success.
}
}, new Realm.Transaction.OnError() {
public void onError(Throwable error) {
// Transaction failed and was automatically canceled.
}
});OnSuccess 和 OnError 并不是必须重载的,重载了的回调函数会在事务成功或者失败时在被调用发生的线程执行。