Realm数据库的那些坑

Realm算是移动端用的比较多的ORM框架了,当初选择的时候入了坑,现在只能在这里慢慢爬了,版本3.1.4。记录一些存在的坑。

Realm的缺点

id不能自增

解决方案:UUID自动生成,或者每次插入的时候获取最大的id往上+1.

实体类只能继承RealmObjet 或者实现RealmModel加@RealmClass注解。

只能直接继承不能间接继承。
我的遇到的问题如下,因为所有的数据库实体类都有一部分同样的字段。我就想把这些字段写到MyBaseObject基类中,再由基类来继承ReamObject。实体类直接继承基类。编译不过。
Error:(14, 8) 错误: Valid model classes must either extend RealmObject or implement RealmModel.

不能参照RealmObject自己实现RealmModel
翻看了一下ReamObject的源码发现它是对RealmModel的实现。天真的以为我也可以这么写一个基类来继承。依然编译不过。一样的错误。
这个RealmModel+注解的方式,简直是来逗我的

暂无解决方案。老老实实一个一个写!

查询的对象带有RealmProxy对象代理

带有代理的对象是可以直接进行Realm数据库操作的。
RealmProxy

实体会多一个ColumnInfo和ProxyState 的对象实例。。ProxyState里面又包含了该RealmProxy对象。
结构如下:
层级嵌套结构
可以看出这是一种递归的存储方式。至于java为什么不溢出,因为它的model直接指向了自己的地址。
问题:做遍历操作会导致ANR和内存溢出
解决方案:

  1. 类似于这种递归的方式如果需要做遍历操作的话。比如说转Json或者一些其他的操作的时候不要忘了忽略掉递归的对象,否则分分钟就内存溢出ANR了。比如Gson忽略某个字段参考
  2. 也可以直接把对象copyfromRealm,拿到真正的对象
    1
    Realm.getDefaultInstance().copyFromRealm(object);

数据库版本更新的那些坑

数据库版本更新介绍

通常来讲数据库更新有三个需要关注的地方。

  • 版本号 .schemaVersion(3)
  • 新版本信息 .migration()
  • 删库更新 .deleteRealmIfMigrationNeeded()
    代码如下:
    1
    2
    3
    4
    5
    6
    7
    Realm.init(this);
    RealmConfiguration config = new RealmConfiguration.Builder()
    .schemaVersion(3)
    .migration(new Migration())
    .deleteRealmIfMigrationNeeded()
    .build();
    Realm.setDefaultConfiguration(config);

版本号就需要每次有做更新schemaVersion往上增加
3 . 4 . 5 …
deleteRealmIfMigrationNeeded() 这句话慎用。

官方说明:

设置这将改变如何处理迁移异常的行为。磁盘上的Realm将被清除并重新创建
加了这句话,如果出现版本号不一致,或者更新出了某些问题。
就会清除掉所有的数据。
migration实现就不做过多介绍了,可以参考这个

坑——数据库更新后不能回退

如果版本更新做了错误的表字段更新,你想要回退。
有两个解决方案(1) 删除掉应用重新安装。(数据会全部丢失)
(2)更新一个版本,把修改还原回去。(工作量大,但是数据不会丢。)

坑——基本类型字段添加

addField(“xxxfield”,long.class);
一定要用基本类型的class,如long.class,int.class,byte.class 不能用Long.class,Byte.class
这个坑将导致上面的坑。解决方案就看上面看上面吧。

realm对于这种经常用数据库存储的应用,真的不好用!!!

坑——Rx流操作

最近想把Realm用Rx流改写一下,然后又发现了他的坑了。

不支持线程切换

在Rx流中我们经常会做线程变换操作,然后Realm并不支持其他非创建线程中访问Realm对象。

线程切换
也就是说,你在哪个线程创建的Realm对象只能在哪个线程中使用。mmp,好吧,谢谢你的异常提醒,但我用的不是很爽。

不是很爽解决方案:把Realm对象创建在子线程
在IO线程中创建一个Realm对象毕竟数据库操作是个耗时操作。

1
Realm.getInstance(new RealmConfiguration.Builder().build());

之后就只能在IO线程中做操作了。别忘了~~ 2333

Rx操作

嗯,一个Rx流的查询操作,莫名其妙给我一直发数据流,相当于无限的查询。后面才发现是因为我的另外一个操作也是有对数据库的查询操作的。 不知道Realm内部怎么实现。就导致这两个的subscribe一直重复走。

解决方案:没有解决方案,建议不要用Rx流。。。。啊啊啊MMP啊 我回不去了!

迎接坑吧!!
realm对于这种经常用数据库存储的应用,真的不好用!!!

By Xiaolong:You have a dream,you got to protect it!