Realm数据库踩坑
注:本文为Realm在项目中的使用注意事项,不能作为使用说明来阅读。
-
Realm使用配置
- 项目build.gradle 中, classpath "io.realm:realm-gradle-plugin:2.2.1"
- app的build.gradle中, apply plugin: 'realm-android' ☆☆☆ 注意:在注入依赖时,确保 apply plugin: 'realm-android' 位于 apply plugin: 'android-apt' 的下方 原因:猜测 realm 依赖注解
-
使用注意事项: Realm数据库,必须在生成realm对象实例的线程中进行操作。因此不需要编写helper定义全局变量。
- 可在Application启动时,初始化一个全局的config
- 在需要数据库操作的activity、fragment或者线程中,Realm.getInstance(config)即可,用完可直接close。
☆ 插入和修改 操作,必须放在事物中进行;
☆ 查询操作可选择直接查询和异步事物查询(当数据量较大,可能会引起ANR的时候),不过后者并不会马上查到数据,是有一定延时的;
☆ 删除语句,需要使用事物,但不能使用异步事物,否则将失败
☆☆ 继承了RealmObject的数据model,如果实现了带参数的构造函数的话,必须实现无参构造函数,否则编译出错。
数据库升级: ☆ 注意:如果你创建Model并运行过,然后修改了Model。那么就需要升级数据库,否则会抛异常。
☆☆☆☆☆ 数据库版本升级时,若要增加字段,则该字段必须设置 FieldAttribute.REQUIRED 属性,否则数据库会出错,打不开。
eg. schema.addField("stock", String.class, FieldAttribute.REQUIRED)
@Index——添加搜索索引 为字段添加搜索索引,这样会使得插入的速度变慢,数据量也变得更大。不过在查询速度将变得更快,建议只在优化读 取性能的特定情况时添加索引。支持索引:String,byte,short,int,long,boolean和Date字段。
具体使用可参考链接:http://www.jianshu.com/p/37af717761cc
以下为数据库升级类RealmMigration使用范例: 注:COPY的,贴在此处作为收藏O(∩_∩)O。
public class Migration implements RealmMigration {
@Override
public void migrate(final DynamicRealm realm, long oldVersion, long newVersion) {
// During a migration, a DynamicRealm is exposed. A DynamicRealm is an untyped variant of a normal Realm, but
// with the same object creation and query capabilities.
// A DynamicRealm uses Strings instead of Class references because the Classes might not even exist or have been
// renamed.
// Access the Realm schema in order to create, modify or delete classes and their fields.
RealmSchema schema = realm.getSchema();
/************************************************
// Version 0
class Person
@Required
String firstName;
@Required
String lastName;
int age;
// Version 1
class Person
@Required
String fullName; // combine firstName and lastName into single field.
int age;
************************************************/
// Migrate from version 0 to version 1
if (oldVersion == 0) {
RealmObjectSchema personSchema = schema.get("Person");
// Combine 'firstName' and 'lastName' in a new field called 'fullName'
personSchema
.addField("fullName", String.class, FieldAttribute.REQUIRED)
.transform(new RealmObjectSchema.Function() {
@Override
public void apply(DynamicRealmObject obj) {
obj.set("fullName", obj.getString("firstName") + " " + obj.getString("lastName"));
}
})
.removeField("firstName")
.removeField("lastName");
oldVersion++;
}
/************************************************
// Version 2
class Pet // add a new model class
@Required
String name;
@Required
String type;
class Person
@Required
String fullName;
int age;
RealmList<Pet> pets; // add an array property
************************************************/
// Migrate from version 1 to version 2
if (oldVersion == 1) {
// Create a new class
RealmObjectSchema petSchema = schema.create("Pet")
.addField("name", String.class, FieldAttribute.REQUIRED)
.addField("type", String.class, FieldAttribute.REQUIRED);
// Add a new field to an old class and populate it with initial data
schema.get("Person")
.addRealmListField("pets", petSchema)
.transform(new RealmObjectSchema.Function() {
@Override
public void apply(DynamicRealmObject obj) {
if (obj.getString("fullName").equals("JP McDonald")) {
DynamicRealmObject pet = realm.createObject("Pet");
pet.setString("name", "Jimbo");
pet.setString("type", "dog");
obj.getList("pets").add(pet);
}
}
});
oldVersion++;
}
/************************************************
// Version 3
class Pet
@Required
String name;
int type; // type becomes int
class Person
String fullName; // fullName is nullable now
RealmList<Pet> pets; // age and pets re-ordered (no action needed)
int age;
************************************************/
// Migrate from version 2 to version 3
if (oldVersion == 2) {
RealmObjectSchema personSchema = schema.get("Person");
personSchema.setNullable("fullName", true); // fullName is nullable now.
// Change type from String to int
schema.get("Pet")
.addField("type_tmp", int.class)
.transform(new RealmObjectSchema.Function() {
@Override
public void apply(DynamicRealmObject obj) {
String oldType = obj.getString("type");
if (oldType.equals("dog")) {
obj.setLong("type_tmp", 1);
} else if (oldType.equals("cat")) {
obj.setInt("type_tmp", 2);
} else if (oldType.equals("hamster")) {
obj.setInt("type_tmp", 3);
}
}
})
.removeField("type")
.renameField("type_tmp", "type");
oldVersion++;
}
}
}