2017-05-28 46 views
0

型號:如何使用Realm創建遞歸關係?

public class Dog extends RealmObject { 
    @PrimaryKey 
    public String id = UUID.randomUUID().toString(); 
    ... other random String attributes 
    public Dog mother; 
} 

活動:

public class CustomActivity extends AppCompatActivity { 
    private Realm realm; 
    private Dog dog = new Dog(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ... 
    realm = Realm.getDefaultInstance(); 
    } 

    @Override 
    public void onDestroy() { 
    super.onDestroy(); 
    realm.close(); 
    } 

    private void setMother(int id) { 
    dog.mother = realm.where(Dog.class).equalTo(ID, id).findFirst(); 
    } 

    private void saveDog() { 
    realm.executeTransactionAsync(new Realm.Transaction() { 
     @Override 
     public void execute(Realm realm) { 
     realm.copyToRealmOrUpdate(dog); 
     } 
    }); 
    } 

} 

當我運行這段代碼是給了我這個錯誤:

Objects which belong to Realm instances in other threads cannot be copied into this Realm instance.

我得到它的工作的唯一方法是通過使用realm.copyFromRealm()但整個對象被複制,我不想這樣做。

我應該單獨保存母親身份證,然後在我的應用程序中隨時查詢母親嗎?

有沒有辦法實現我想要做的,而不是複製整個對象?


編輯:

我原本以爲整個對象是使用realm.copyFromRealm()複製的,因爲它會在瀏覽器領域的方式。
我剛剛測試了更新dog.mother中的一個字段,並更新了鏈接對象,這意味着它不是副本。
我仍然不知道是否是最好的方式或正確的方式來實現我想做的事情,但它做我想做的事情。

+1

這個問題的答案將取決於母親是否已經在Realm中,以及您希望如何更新。你可以爲你的圖創建一個完整的內存表示,並在其上執行'copyToRealmOrUpdate',但這可能不是你想要的。 –

+0

母親將永遠處於境界第一。 對不起,但我不確定是否明白'_create your memory in-memory representation of your graph and do copyToRealmOrUpdate_'是什麼意思。我在我的例子中不是在做什麼?我的最終目標是通過獲得對母親的引用來創建鏈接。我目前這樣做: 'dog.mother = realm.copyFromRealm(realm.where(Dog.class).equalTo(ID,id).findFirst());' 可以嗎? – seb

回答

1
private Realm realm;  

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    ... 
    realm = Realm.getDefaultInstance(); //<--- this is on ui thread 

realm.executeTransactionAsync(new Realm.Transaction() { 
    @Override 
    public void execute(Realm realm) { 
    realm.copyToRealmOrUpdate(dog); // <-- this is on background thread 
    //... 


private void setMother(int id) { 
    dog.mother = realm.where(Dog.class).equalTo(ID, id).findFirst(); // <-- uses UI-thread Realm stored as field 

所以,如果你在後臺線程中使用setMother(),你會訪問UI線程領域,它會拋出IllegalStateException。

您需要將給定線程的Realm傳遞給該方法。

private void setMother(Realm realm, Dog dog, int id) { 
    dog.mother = realm.where(Dog.class).equalTo(ID, id).findFirst(); 
    } 

    private void saveDog() { 
    realm.executeTransactionAsync(new Realm.Transaction() { 
     @Override 
     public void execute(Realm realm) { 
     Dog _dog = realm.copyToRealmOrUpdate(dog); 
     setMother(realm, _dog, id); 
     } 
    }); 
+0

謝謝你的回答,它確實幫助我瞭解我的錯誤。還有一件事情,比方說,我想顯示一些母親的屬性預覽,直到用戶按下保存按鈕。我應該查詢母親一次,並用copyFromRealm將它鏈接到我的新狗,或者查詢母親我要顯示它的位置(不鏈接新狗),然後在用戶決定保存時進行第二次查詢?這裏最好的做法是什麼? – seb

+1

'查詢母親想要顯示它的位置(不鏈接新狗),然後在用戶決定保存時進行第二次查詢? – EpicPandaForce

1

發生異常是因爲您在UI線程上構造了Dog對象,然後將它傳遞給異步工作線程,但這意味着您還將引用傳遞給mother,這是不允許的。相反,你需要做的設置在異步方法是這樣的:

private void saveDog() { 
    realm.executeTransactionAsync(new Realm.Transaction() { 
     @Override 
     public void execute(Realm realm) { 
     // This will give you mother reference on the correct thread 
     setMother(motherId, dog); 
     realm.copyToRealmOrUpdate(dog); 
     } 
    }); 
} 
+0

謝謝你的回答。我會在今天晚上嘗試它,並將其標記爲接受,如果它有效。 – seb