場景
我有一個典型的UI線程和工作線程場景。我做了一些工作,並在工作線程中將結果寫入領域。結果是一個帶有一些String字段的簡單RealmObject。完成此操作後,我將UI線程上的事件發送到我的活動(使用Otto事件總線)以報告工作已完成。Realm在多線程場景中給出陳舊結果
在我的Activity中收到事件後,我查詢結果,並且字符串字段沒有用寫入值更新。
在工作線程:
// Did some work. Got some result
// Write to realm
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
MyResult result = realm.where(MyResult.class)
.equalTo("id", 1)
.findFirst();
result.someString = "hello world";
}
});
} finally {
if(realm != null){
realm.close();
realm = null;
}
}
//Post job done event on Otto bus
uiThreadBus.post(new JobDoneEvent());
在活動時間:
// Upon received JobDoneEvent
MyResult result = realm.where(MyResult.class)
.equalTo("id", 1)
.findFirst();
// result.someString is some stale value
Log.d("TAG", result.someString);
我做什麼
,如果我在一個事務塊包裹查詢,則RealmObject將達到我意識到日期當我嘗試打印它。
// Upon received JobDoneEvent
MyResult result = null;
try{
realm.beginTransaction();
result = realm.where(MyResult.class)
.equalTo("id", 1)
.findFirst();
realm.cancelTransaction();
}
catch(Exception e) {
realm.cancelTransaction();
}
// result.someString is up-to-date
Log.d("TAG", result.someString);
問題
什麼是起牀最新RealmObject正確的方法是什麼?我是否每次都必須將它們放入事務塊中以強制它與工作線程「同步」?有我可以遵循的模式嗎?
開始領域事務(通過Realm#beginTransaction()或Realm#executeTransaction())做什麼?它阻止其他線程的讀/寫嘗試嗎?在交易中執行長期操作(如網絡請求)是否有任何傷害?
編輯
實際代碼:
// Did some work. Got some result
// Write to realm
try {
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
User managedUser = result.payload.createOrUpdateInRealm(realm,
MyApplication.getPrimaryKeyFactory());
Log.i("TAG", "updated user: " + managedUser.getId());
}
});
} finally {
if(realm != null) {
realm.close();
realm = null;
}
}
//Post job done event on Otto bus
MyApplication.getBusInstance().post(new LoginEvent());
// Writing to realm method
public User createOrUpdateInRealm(@NonNull Realm realm,
@NonNull PrimaryKeyFactory pkFactory) {
User managedUser = realm.where(User.class)
.equalTo("primary_key", pk)
.findFirst();
managedUser.setId(xUserId);
return managedUser;
}
// Event receiving method in Activity
@Subscribe
public void loginEventReceived(LoginEvent event) {
User user = mRealm.where(User.class)
.equalTo("primary_key", mPk)
.findFirst();
Log.d("TAG", user.getId());
}
嘗試使用setSomething()方法。我相信領域代理對象使用它。不確定,但值得嘗試 –
@Tim我在我的實際代碼中使用了setSomething()方法。結果仍然是一樣的。給出的例子僅用於說明目的。 – Weizhi
建議:發佈你的實際代碼 –