Realm Java的學習、應用、總結

從React Native珠三角沙龍會議瞭解到Realm這個開源庫,而後開始學習、理解和使用Realm。Realm是跨平臺、支持多種主流語言,這裏主要是對Realm Java結合實際項目的一些狀況進行記錄。java

Realm是什麼?

Realm官網:https://realm.io/cn/android

Realm,爲移動設備而生!替代 SQLite 和 Core Data。爲你省下數週的時間和數千行的代碼,幫你創造出更棒的用戶體驗。--Realm官網git

從上面官網的定義,咱們大概知道它是一個移動端的數據庫。想了解更多到官網,在這裏不作過長的介紹。github

Realm Android的性能

對於Realm Android的性能也是咱們比較關注的一個問題,我也是看到Realm的性能比其餘數據庫要快,因此纔去瞭解以及學習它。下面從官網的三張圖片來了解一下它的性能。數據庫

  • 插入操做:在同一個事務裏,每秒插入100K條記錄(越高表明性能越好) session

  • 統計操做:每秒能在100K條數據中進行查詢後count的次數(越高表明性能越好) dom

  • 查詢操做:在100K中進行一次遍歷查詢(越高表明性能越好) 異步

Realm不是基於SQLite的ORM,它是基於C++ 存儲引擎的。因此,它的速度至關來講比較快的,可是目前它也引起了應用的安裝包大小問題。(估計目前他們正在優化這個問題) 詳細性能內容查看官方的文檔: https://realm.io/news/realm-for-android/#realm-for-android數據庫設計

爲何選擇Realm Java?

目前在開發應用的IM模塊使用到數據庫ormlite存儲數據。每次打開應用切換到消息列表的時候要等一會才加載出來,從會話點聊天列表加載聊天記錄(聊天記錄上W條)要轉轉轉轉轉纔出來。看到Realm性能寫得好像好厲害的樣子,因此嘗試運用Realm Java。 可能你會問,爲何不選擇DBFlow,GreenDAO,ActiveAndroid? DBFlow在建立數據庫的時候,數據庫名稱和版本號都是使用static final修飾變量,而個人應用數據庫設計是每一個帳號對應一個數據庫,因此DBFlow在切換數據庫的時候,有點力不從心,最張放棄使用DBFlow。而GreenDAO性能上也不錯,可是建立Model和數據庫升級挺折騰的,總得來講greenDAO投入成本高。(我比較懶~~),ActiveAndroid沒有嘗試過,有空能夠試一下。工具

Relam Java(v0.91.0)目前遇到的一些問題

Realm Java集成

Realm Java的GitHub地址:https://github.com/realm/realm-java 我的推薦按照官網文檔集成Realm Java。由於我以前按照Github中的文檔集成Realm Java沒有成功,最後按照官網的就能夠了。 若是你的項目有多個Module的話。以下圖,則能夠在util的Module加入Realm Java就能夠了。

Realm 數據庫文件大小

這裏我測試了一下引入Realm Java後apk大小的變化。以下圖,能夠看到引入後apk足足大了4M。

 

 備註:如下的代碼均運行在子線程,這裏沒有使用Realm異步查詢。

不支持自增ID

在新增數據表的時候,每每定義自增ID,這樣作是下降與業務邏輯的耦合。

1 //ormlite能夠定義自增id
2 @DatabaseField(generatedId = true)
3 public int _id;
1 //realm java 不支持自增id,這裏我使用了UUID來生成,我也沒辦法了
2 //使用咱們項目中已經使用到id.
3 public String _id = UUID.randomUUID().toString();

 

不支持limit

場景:每次找出符合條件的20記錄並返回。 然而,Realm Java沒有這樣的操做。

這個在github中的issue有人提交了。here 看下面的代碼,我找出全部符合條件的記錄,而後根據傳入的大小將結果截取並返回。(Y的,若是記錄上W條的話,不就很坑嗎)

 1 realm.beginTransaction();
 2 String [] orderFiled = {"time","_id"};
 3 Sort [] sorts = {Sort.DESCENDING, Sort.DESCENDING};
 4 RealmResults<Message> results = realm.where(Message.class)
 5     .equalTo("sessionType",  ModelFileds.SESSION_TYPE_MESSAGE_STRANGER)
 6     .equalTo("sessionId", sessionId)
 7     .or()
 8     .equalTo("sessionType", ModelFileds.SESSION_TYPE_MESSAGE_FRIEND)
 9     .equalTo("sessionId", sessionId)
10     .findAllSorted(orderFiled, sorts);
11 realm.commitTransaction();
12 return results.subList(0, size);

 

update操做

場景:找出符合條件的記錄,並對某個字段進行值的修改。

  • ormlite使用UpdateBuilder就能夠完成這個操做了。
 1 localSqliteHelper = new LocalSqliteHelper(mAccount.getUuid());
 2 UpdateBuilder<MessageModel, Integer> updateBuilder
 3      = getMessageDao(localSqliteHelper
 4 .getWritableDatabase()).updateBuilder();
 5 updateBuilder.where()
 6     .eq("sessionId", sessionId).and()
 7     .eq("sessionType", sessionType).and()
 8     .eq("sessionSecondId", sessionSecondId).and()
 9     .eq("sessionSecondType", sessionSecondType).and()
10     .eq("isSend", MessageModel.OTHER_TO_ME);
11 updateBuilder.updateColumnValue("status", 1);
12 return updateBuilder.update();

 

  • Realm Java我只能這樣寫了。(將符合條件的記錄遍歷賦值,我也無語了)
 1 realm.beginTransaction();
 2 RealmResults<Message> messages = realm.where(Message.class)
 3         .equalTo("sessionId", sessionId)
 4         .equalTo("sessionType", sessionType)
 5         .equalTo("sessionSecondId", sessionSecondId)
 6         .equalTo("sessionSecondType", sessionSecondType)
 7         .equalTo("isSend", MessageModel.OTHER_TO_ME)
 8         .findAll();
 9 for (Message msg : messages)
10     msg.status = 1;
11 realm.copyToRealmOrUpdate(messages);
12 realm.commitTransaction();

 

like模糊查詢

場景:輸入關鍵字顯示匹配關鍵字的記錄。

  • ormlite使用like就能夠了。
 1 LocalSqliteHelper localSqliteHelper = null;
 2 try {
 3     localSqliteHelper = new LocalSqliteHelper(mAccount.getUuid());
 4     return getProjectDao(localSqliteHelper.getWritableDatabase())
 5             .queryBuilder().orderBy("update_date", false)
 6             .where()
 7             .like("name", "%/" + keyword + "/%").query();
 8 } catch (SQLException e) {
 9     throw new DBException(e);
10 } finally {
11     if (localSqliteHelper != null) {
12         localSqliteHelper.close();
13     }
14 }

 

  • Realm Java先找出符合條件,而後再判斷是否包含關鍵字。
 1 realm.beginTransaction();
 2 RealmResults<Project> results = realm.where(Project.class)
 3     .findAllSorted("update_date", Sort.DESCENDING);
 4 realm.commitTransaction();
 5 if(results != null && results.size() > 0){
 6   for(int i = results.size() -1; i >=0; i--){
 7       if(!results.get(i).name.contains(keyword)){
 8           results.remove(i);  
 9       }
10   }
11 }
12 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/


之前我不太明白大神們說的多看官方文檔、多看源碼這個學習方法,那時候我總種感受是他們在忽悠我。之前的我當接觸到新的技術時,第一反應是百度,並且很是很是很是討厭看官方文檔(乾脆就不看了);如今我老是渴望深刻理解它的使用、原理,也慢慢地習慣閱讀看官方文檔。改變的過程老是不那麼容易,須要你的堅持。生活未嘗不是須要經過你本身不斷地努力去改變呢~

相關文章
相關標籤/搜索