说说 Realm 在 Android 上的坑

   2016-11-13 0
核心提示:1.前言新项目使用了大名鼎鼎的realm,在网络上看到大量安利realm的文章,但是在使用的过程中却遇到了很多问题,这里记录下两个多月以来遇见的问题。希望大家能够理性选择,不要人云亦云。当然,,realm文档中也给出了一些当前的限制,但是,我们今天要说的,不

1.前言

新项目使用了大名鼎鼎的realm,在网络上看到大量安利realm的文章,但是在使用的过程中却遇到了很多问题,这里记录下两个多月以来遇见的问题。希望大家能够理性选择,不要人云亦云。当然,,realm文档中也给出了一些当前的限制,但是,我们今天要说的,不仅仅是这些。

realm-java文档地址

 说说 Realm 在 Android 上的坑

2.线程的限制

通常来讲,我们查询数据库会开一个子线程查询,这次,我们也没例外,简简单单的写两行代码,如下。

realm.where(User.class)
                        .findAll()
                        .asObservable()
                        .observeOn(Schedulers.io())
                        .subscribeOn(AndroidSchedulers.mainThread())
                        .subscribe(new Action1<RealmResults<User>>() {
                            @Override
                            public void call(RealmResults<User> users) {
                                users.get(0);
                            }
                        });

当我们满心欢喜的运行起来的时候,mdzz,crash了。日志如下。

 说说 Realm 在 Android 上的坑

what,realm对象只能在他被创建的线程中访问,搞毛啊。即使你查询速度快,也提供了异步查询,可我就想在子线程和主现场之间切换玩。这。。。不是坑么。

3.RealmList的问题

说到这里,我们先来看看realm支持的数据类型。

 说说 Realm 在 Android 上的坑

很好,基本能满足我们的需求。并且还提供了RealmList来提供给我们使用。这次,我要实现这样的需求,在a1中查询数据出来,传递到a2中,由于实体较复杂,内含多对一的对应关系,这里是用RealmList来处理了。写好代码,不幸的是,又crash了。

 说说 Realm 在 Android 上的坑

这次的错误,预示这我们,realm intent传值又问题。

我们的实体对象是这样写的。

public class User extends RealmObject  implements Serializable{
    public String name;
    public RealmList<Cursor> cursors;
}

忽略我不标准的写法

很明显,问题出在了realmlist这里,我们进去一看,fuck,和arraylist的区别很明显。如图。

 说说 Realm 在 Android 上的坑  说说 Realm 在 Android 上的坑

可以看到,arraylist是实现的Serializable接口的,而realmlist却没有,因此,我们在使用用了realmlist的实体类的时候,使用intent传值就回出现问题,要注意了。

解决办法:我们只能存入数据库,在第二个界面进行查询使用,这不是我想要的。

4.查询出来的数据,intent传值问题

没想到吧,即使简简单单的查询出来的数据,在使用intent传值还是有问题。这次我的实体类变成这样。

public class User extends RealmObject  implements Serializable{
    public String name;
}

接下来,我们将查询出来的数据,使用intent传递到第二个界面。

 说说 Realm 在 Android 上的坑

 说说 Realm 在 Android 上的坑

细心的同学应该看出来了,这里crash的原因是因为我们userrealmproxy不能被序列化的问题。但是,我们没有传过userrealmproxy啊。这是因为我们查询出来的数据,不再是我们想要的对象,而是realm用apt给我们生成的实体类的子类,或者说是实体类的代理类,在realm中起到作用的,就是这些个代理类。在build目录下我们能找到不少。如图。

 说说 Realm 在 Android 上的坑

解决办法,实现cloneable接口,深clone或者是把查询到的值手动复制给我们new的实体类对象。这也不是我们想要的结果

5. RealmChangeListener的坑

 说说 Realm 在 Android 上的坑

我们确实需要它来通知我们异步查询什么时候结束。但是,我们要注意后半句,当realmresults对象更新的时候,也会通知我们。

现在,我们思考一个场景,我们要在进入页面的时候,查询数据,显示界面。并且同时请求网络,更新数据,更新界面,没错,这个场景我们确实狠需要,当我们使用RealmChangeListener的时候,RealmChangeListener会通知我们两次,一次是查询数据库完成的,一次是更新的,但是,我们并不需要。因此,大家要做好处理。

6. 数据库版本迁移的问题

从realm文档来看,数据库版本迁移不复杂,但是工作量较大,我们需要知道每次实体类的变更,事实上,我们要做的可能更多,我这里就不模拟迁移了,只给出上次迁移遇到的问题及结果。

新加字段问题当我们新加字段的时候,如果没有@Required注解,那么我们需要设置 .setNullable(字段,false) ,没错,就是false。按理来说,我们不是应该为true么?但是,通过追源码得知。设置true,会抛出 throw new IllegalStateException("Field is already required: " + fieldName);

但是要注意,新加的类不需要setnullable

上周四血的教训!!!

7 总结

由于使用时间较短,暂时只发现这个。最后,选择realm,一定要考虑清楚是否真的需要,是否想好了怎么处理这些问题。

 
标签: Realm 安卓开发
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

点击排行