如何使用Realm创建递归关系?

时间:2017-05-28 17:30:18

标签: java android 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中的字段,它更新了链接对象,这意味着它不是副本 我仍然不知道这是实现我想做的最好的方式还是正确的方法,但它能做到我想要的。

2 个答案:

答案 0 :(得分:1)

您的异常发生是因为您在UI线程上构造了Dog对象,然后将其传递给异步工作线程,但这意味着您还将引用传递给mother,而不是#39} ; t允许。相反,您需要在async方法中进行设置,如下所示:

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);
      }
    });
}

答案 1 :(得分: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线程Realm,并且它会抛出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);
      }
    });