2015-07-03 50 views
3

我正在開發與Android Annotations的Android應用程序。對於持久性,我首先在SQLite之上使用了一個Content Provider(非常複雜)。然後,我發現了Realm。它似乎非常酷,直到我必須被通知插入,使我的RecyclerView動態。爲了通知插入,我創建了一個叫做RealmProxy的單例類,使用copyToRealm()的代理方法,以及一個實現爲RealmListener的接口。我在我的copyToRealm()方法中調用了註冊偵聽器,向他們傳遞了添加的RealmObject,因此我可以填充我的SortedList(支持庫列表,設計用於RecyclerView)RecyclerView適配器。我還使用我的RealmListener接口在保存後立即通過網絡發送新的對象。Android中JPA的領域或紙張?

編譯並運行後,我得到了和IllegalStateException(不正確的線程域的訪問。境界對象只能創建它們的線程上進行訪問。),因爲我是從UI線程獲取領域實例,但我寄過去網絡在後臺線程顯然。爲什麼我會得到這個錯誤?每當我的JSON序列化庫LoganSquare(基於Jackson在後臺調用我的RealmObject上的獲取器以通過網絡發送)時,將拋出此異常。這讓我討厭Realm線程策略以及細粒度通知不是內置的事實。此外,Realm不允許我定義任何自定義方法。我甚至無法在Realm對象中實現Comparable

當我今天看到Paper感謝Android Arsenal和Pushbullet)時,我對一個沒有頭痛的JPA解決方案非常感興趣。看起來很簡單,對列表,地圖和任何沒有擴展特殊類的類都沒有限制(Realm需要擴展RealmObject並使用RealmList,而不是通用列表,這是java不喜歡的,我強迫我複製列表)。

編輯: 今天我發現SnappyDB。它使用與Paper相同的序列化庫(Kryo),它看起來與Paper非常相似,具有更多用於密鑰管理的功能。

所以我的問題是:

我應該尋找解決辦法,並繼續使用領域,如果是,其變通方法,或者我應該使用Paper,或SnappyDB呢?有沒有人使用PaperSnappyDB爲Android?

所有最優秀的

+0

請問你目前Realm的問題是什麼?是否在線程間使用Realm和RecyclerView?這個[類似的問題](http://stackoverflow.com/questions/28995380/best-practices-to-use-realm-with-a-recycler-view)有幫助嗎? – beeender

+0

當我在後臺和UI中使用相同的'RealmObject'時,我得到了描述'IllegalStateException'。由於我的應用程序是RESTful的,我必須在後臺處理網絡,但是我每次在Realm中添加一個對象時都不得不重新查詢,這是不切實際且效率低下的。 –

回答

0

如果你的問題是關於當它在後臺得到改變如何在UI線程更新您的對象,它實際上是相當簡單的。

例如,在你的UI線程,你可以這樣做:

private Dog dog; 
private RealmChangeListener listener = new RealmChangeListener() { 
    @Override 
    // This will be called when the commitTransaction gets called 
    // in the background thread 
    public void onChange() { 
     // It would changed to "EFG" automatically in next UI loop after 
     // you updated it in the background thread. 
     String name = dog.getName(); 
    } 
}; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    dog = realm.where(Dog.class).equalTo("id", 42).findFirst(); 
    // Assume it is "ABC" now 
    String name = dog.getName(); 
    // Register the listener 
    realm.addChangeListener(listener); 
} 

而且更新就像個後臺服務的狗:

// This realm will be a different instance created in this thread. 
dog = realm.where(Dog.class).equalTo("id", 42).findFirst(); 
realm.beginTransaction(); 
dog.setName("EFG"); 
realm.commitTransaction(); 

IllegalStateException是因爲:

跨線程使用Real的唯一規則是記住Realm,RealmObject或RealmResults實例不能通過sed跨線程。當你想從一個不同的線程訪問相同的數據時,你應該簡單地獲得一個新的Realm實例(即Realm.getInstance(Context context)或它的堂兄弟)並通過查詢來獲取你的對象。這些對象將映射到磁盤上的相同數據,並且可以從任何線程寫入&! 見見文件here

而且你可能需要RealmBaseAdapter它可以使建立一個ListView與境界非常的方便。您可以找到示例here

+0

'RealmChangeListener'通知任何更改,但不提供有關更改的任何信息。 我正在使用SortedList的RecyclerView,並且需要針對特定​​類(甚至可以是特定查詢)獲取插入和刪除的通知。我不想更新所有內容,每次RealmObject更改時都會丟失UI狀態。我知道'IllegalStateException'源,但是我不能通過參數傳入的對象通知因爲這個錯誤的線程策略... –

+0

這是真的。我們有一個[未解決的問題](https://github.com/realm/realm-java/issues/989)在github上進行跟蹤。請問您對目前的執行情況有何顧慮?是否收到太多無用的通知? – beeender

+0

我希望能夠跨線程使用RealmObjects,並獲取參數中的任何已添加或更新的對象。我需要細粒度的通知,因爲我使用RecyclerView,需要通知插入,更新和刪除操作以更好地播放內容更改動畫。 –

0

JPA不是解決方案,它是Java持久性的定義。一旦你選擇JPA,你需要找到一個實現。在Java世界中,使用最廣泛的實現是Hibernate。另外,您可以使用Hibernate ORM而不使用JPA。

在Android上,OrmLite爲JPA的一個子集提供了一個實現。但是,因爲它只是一個子集,所以您可以跳過JPA並使用等效的Ormlite註釋。我在我的服務器應用程序中使用Hibernate實現的JPA,以及Android上沒有JPA的Ormlite。我絕對推薦Ormlite。