天天看點

解決 Realm Only valid managed objects can be copied from Realm.

最近項目用到了ORM資料庫Realm,功能強大,也非常友善,同時也帶來了很多奇葩的問題

比如這個異常,找了半天也沒有解決方案,經過千辛萬苦終于找到了,這裡做個記錄,防止

以後再次入坑

先看代碼

public RealmChatMessage getChatMessageSynchronous(String messageId) {
        RealmChatMessage realmChatMessage = null;
        try(Realm realm = Realm.getDefaultInstance()) {
            realmChatMessage = realm.where(RealmChatMessage.class)
                    .equalTo("messageId", messageId)
                    .findFirst();
        }
        return realmChatMessage;
    }

    public void sendMessage(String messageId, boolean playSound) {
        RealmChatMessage chatMessage = realmChatDao.getChatMessageSynchronous(messageId);
        if (chatMessage != null) {
            try(Realm realm = Realm.getDefaultInstance()) {
                RealmChatMessage unmanagedChatMessage = realm.copyFromRealm(chatMessage);
                sendMessage(unmanagedChatMessage, playSound);
            }
        } 
    }
           

表面上看沒啥問題,但是一運作到15行就報标題的錯,然後crash

原因是上一個方法傳過來的chatMessage說是Invalid Object,真的是百思不得其解

最後發現Realm查詢到一條資料的對象要再次使用Realm操作就要保證資料庫不能關閉,

而getChatMessageSynchronous() 裡面用了try(),()小括号中的對象會在try執行完畢

後自動釋放掉,當然對象必須實作AutoCloseable接口,最終導緻Realm資料庫關閉

是以修改後的代碼如下

public RealmChatMessage getChatMessageSynchronous(String messageId) {
        return Realm.getDefaultInstance().where(RealmChatMessage.class)
            .equalTo("messageId", messageId)
            .findFirst();
    }

    public void sendMessage(String messageId, boolean playSound) {
        RealmChatMessage chatMessage = realmChatDao.getChatMessageSynchronous(messageId);
        if (chatMessage != null) {
            try(Realm realm = Realm.getDefaultInstance()) {
                RealmChatMessage unmanagedChatMessage = realm.copyFromRealm(chatMessage);
                sendMessage(unmanagedChatMessage, playSound);
            }
        } 
    }
           

發現差別了吧,哈哈,現在又可以愉快的玩耍了

解決 Realm Only valid managed objects can be copied from Realm.