【发布时间】:2016-11-18 23:38:16
【问题描述】:
场景
我有一个典型的 UI 线程和工作线程场景。我做了一些工作并将结果写入工作线程中的领域。结果是一个带有一些字符串字段的简单 RealmObject。完成此操作后,我将 UI 线程上的事件发送到我的 Activity(使用 Otto 事件总线)以报告工作已完成。
在我的 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() 方法。结果还是一样。给出的示例仅用于说明目的。
-
一条建议:发布您的实际代码
-
@Tim 你去吧
-
谢谢。顺便说一句,只需删除其他代码。它会让人们感到困惑