Realm Java的学习、应用、总结

作者: Hanwen1001 | 来源:发表于2016-05-23 16:51 被阅读3834次

    从React Native珠三角沙龙会议了解到Realm这个开源库,然后开始学习、理解和使用Realm。Realm是跨平台、支持多种主流语言,这里主要是对Realm Java结合实际项目的一些情况进行记录。

    Realm是什么?

    Realm官网:https://realm.io/cn/

    Realm,为移动设备而生!替代 SQLite 和 Core Data。为你省下数周的时间和数千行的代码,帮你创造出更棒的用户体验。--Realm官网

    从上面官网的定义,我们大概知道它是一个移动端的数据库。想了解更多到官网,在这里不做过长的介绍。

    Realm Android的性能

    对于Realm Android的性能也是我们比较关注的一个问题,我也是看到Realm的性能比其他数据库要快,所以才去了解以及学习它。下面从官网的三张图片来了解一下它的性能。

    • 插入操作:在同一个事务里,每秒插入100K条记录(越高代表性能越好)


      Realm 数据库文件大小

      这里我测试了一下引入Realm Java后apk大小的变化。如下图,可以看到引入后apk足足大了4M。


      没有引入Realm Java 引入Realm Java

      备注:以下的代码均运行在子线程,这里没有使用Realm异步查询。

      不支持自增ID

      在新增数据表的时候,往往定义自增ID,这样做是降低与业务逻辑的耦合。

      //ormlite可以定义自增id
      @DatabaseField(generatedId = true)
      public int _id;
      
      //realm java 不支持自增id,这里我使用了UUID来生成,我也没办法了
      //使用我们项目中已经使用到id.
      public String _id = UUID.randomUUID().toString();
      

      不支持limit

      场景:每次找出符合条件的20记录并返回。
      然而,Realm Java没有这样的操作。
      这个在github中的issue有人提交了。here
      看下面的代码,我找出所有符合条件的记录,然后根据传入的大小将结果截取并返回。(Y的,如果记录上W条的话,不就很坑吗)

      realm.beginTransaction();
      String [] orderFiled = {"time","_id"};
      Sort [] sorts = {Sort.DESCENDING, Sort.DESCENDING};
      RealmResults<Message> results = realm.where(Message.class)
          .equalTo("sessionType",  ModelFileds.SESSION_TYPE_MESSAGE_STRANGER)
          .equalTo("sessionId", sessionId)
          .or()
          .equalTo("sessionType", ModelFileds.SESSION_TYPE_MESSAGE_FRIEND)
          .equalTo("sessionId", sessionId)
          .findAllSorted(orderFiled, sorts);
      realm.commitTransaction();
      return results.subList(0, size);
      

      update操作

      场景:找出符合条件的记录,并对某个字段进行值的修改。

      • ormlite使用UpdateBuilder就可以完成这个操作了。
      localSqliteHelper = new LocalSqliteHelper(mAccount.getUuid());
      UpdateBuilder<MessageModel, Integer> updateBuilder
           = getMessageDao(localSqliteHelper
      .getWritableDatabase()).updateBuilder();
      updateBuilder.where()
          .eq("sessionId", sessionId).and()
          .eq("sessionType", sessionType).and()
          .eq("sessionSecondId", sessionSecondId).and()
          .eq("sessionSecondType", sessionSecondType).and()
          .eq("isSend", MessageModel.OTHER_TO_ME);
      updateBuilder.updateColumnValue("status", 1);
      return updateBuilder.update();
      
      • Realm Java我只能这样写了。(将符合条件的记录遍历赋值,我也无语了)
      realm.beginTransaction();
      RealmResults<Message> messages = realm.where(Message.class)
              .equalTo("sessionId", sessionId)
              .equalTo("sessionType", sessionType)
              .equalTo("sessionSecondId", sessionSecondId)
              .equalTo("sessionSecondType", sessionSecondType)
              .equalTo("isSend", MessageModel.OTHER_TO_ME)
              .findAll();
      for (Message msg : messages)
          msg.status = 1;
      realm.copyToRealmOrUpdate(messages);
      realm.commitTransaction();
      

      like模糊查询

      场景:输入关键字显示匹配关键字的记录。

      • ormlite使用like就可以了。
      LocalSqliteHelper localSqliteHelper = null;
      try {
          localSqliteHelper = new LocalSqliteHelper(mAccount.getUuid());
          return getProjectDao(localSqliteHelper.getWritableDatabase())
                  .queryBuilder().orderBy("update_date", false)
                  .where()
                  .like("name", "%/" + keyword + "/%").query();
      } catch (SQLException e) {
          throw new DBException(e);
      } finally {
          if (localSqliteHelper != null) {
              localSqliteHelper.close();
          }
      }
      
      • Realm Java先找出符合条件,然后再判断是否包含关键字。
      realm.beginTransaction();
      RealmResults<Project> results = realm.where(Project.class)
          .findAllSorted("update_date", Sort.DESCENDING);
      realm.commitTransaction();
      if(results != null && results.size() > 0){
        for(int i = results.size() -1; i >=0; i--){
            if(!results.get(i).name.contains(keyword)){
                results.remove(i);  
            }
        }
      }
      return results;
      

      FAQ

      更多问题可以看官网的FAQ:
      https://realm.io/cn/docs/java/latest/#faq

      stetho-realm工具

      如果使用Realm Java,推荐结合stetho-realm工具进行使用。stetho-realm可以查看Realm数据,但是这个工具目前还不支持数据操作。

      扩展阅读

      最后,安利大家认真阅读Realm官网发布的文章。文章有一定的技术含金量的喔~文章都有中文翻译的,你再也不用担心看不懂!
      链接:https://realm.io/cn/news/


      以前我不太明白大神们说的多看官方文档、多看源码这个学习方法,那时候我总种感觉是他们在忽悠我。以前的我当接触到新的技术时,第一反应是百度,而且非常非常非常讨厌看官方文档(干脆就不看了);现在我总是渴望深入理解它的使用、原理,也慢慢地习惯阅读看官方文档。改变的过程总是不那么容易,需要你的坚持。生活何尝不是需要通过你自己不断地努力去改变呢~

    相关文章

      网友评论

      • gzfgeh:太大,太年轻,决定用GreenDao了
      • 3b3b0abb0d3b:感谢了,感谢!感谢!想到了一个方法,把主键传递给activity,然后再查找。你有什么方法吗
        皇马船长:@AyaC3J 官方文档 给出的解决方案就是这样的
      • 3b3b0abb0d3b:博主,有没有遇到给对象序列化的问题呢。
        public class Note extends RealmObject implements Serializable {}
        这样子在activity之间传递是不可以的。有什么解决办法吗
        Hanwen1001:@AyaC3J 我对不支持Intent的理解是因为RealmObject不支持跨线程,所以不可以使用Intent来传递对象。
        Hanwen1001:@AyaC3J 你的问题官方文档也提到了不可以用Intent传递RealmObject对象,官方也提供解决的方案,你可以查看一下!https://realm.io/cn/docs/java/latest/#intents
      • 冷师傅_:你好,博主,realm的分页数据怎么取?一直没有找到解决方案
        冷师傅_:好的谢谢!非常有帮助!
        Hanwen1001:@冷师傅_ 现在官网还没有很好的解决方案,你可以找出符合条件的记录然后进行处理,以达到分页的效果。你可以查看Realm Java的issue的#544(https://github.com/realm/realm-java/issues/544)
      • 猫的天空之程:用ndk abifilter去除不需要的架构,可以减少引入库的大小
        Hanwen1001:@猫的天空之程 官网也有提到这种方法来减少apk的大小!文章的例子只是演示加入Realm前后安装包的对比。
      • Benhero:4M :scream:
        李斯维:@奔ben苯笨 就是因为这个原因,我所在的公司一直不使用realm。Android的数据框架基本够用,就是麻烦点。
        Hanwen1001:@Jenchar 应用开发的实践是能不用数据库就尽量不用数据库! :blush:
        Jenchar:@奔ben苯笨 这数值也吓到了我。。
        觉得不是大项目 ,不需要快速拿 到数据的话,这个realm java比sqlite还不好。

      本文标题:Realm Java的学习、应用、总结

      本文链接:https://www.haomeiwen.com/subject/qigorttx.html