根据我的理解,Realm
只能从主线程访问。
我使用两个领域,一个用于存储“脏”数据,经过验证,将被移动到真实领域。
到目前为止一直很好,但我无法在主线之外找到这样做的方法。
如果我使用realm.executeTransactionAsync()
写入真实域,我将无法在事务线程内访问脏域或其RealmResults
。
唯一的解决方法是在主线程上使用dirtyRealm.copyFromRealm()
- 这可能会阻塞线程更长的时间,对吗?
这是正确的方法还是有更好的解决方案?
答案 0 :(得分:1)
根据我的理解,Realm只能从主线程访问。
这是一种误解。虽然Realm仅在looper线程(例如主线程)上自动更新,但这并不意味着您无法在任何线程上创建新的Realm实例。
如果你想在后台线程上打开一个领域,你可以轻松地做到这一点:
new Thread(new Runnable() {
@Override
public void run() {
Realm firstRealm = null;
Realm secondRealm = null;
try {
firstRealm = Realm.getInstance(firstConfiguration);
secondRealm = Realm.getInstance(secondConfiguration);
firstRealm.beginTransaction();
secondRealm.beginTransaction();
RealmResults<SomeObject> someObjects = firstRealm.where(SomeObject.class)
.equalTo(SomeObjectFields.VALID, true)
.findAll();
secondRealm.copyToRealmOrUpdate(someObjects); // I am not sure if you have to detach it first.
someObjects.deleteAllFromRealm();
secondRealm.commitTransaction();
firstRealm.commitTransaction();
} catch(Throwable e) {
if(firstRealm != null && firstRealm.isInTransaction()) {
firstRealm.cancelTransaction();
}
if(secondRealm != null && secondRealm.isInTransaction()) {
secondRealm.cancelTransaction();
}
throw e;
} finally {
if(firstRealm != null) {
firstRealm.close();
}
if(secondRealm != null) {
secondRealm.close();
}
}
}
}).start();
要访问UI线程上的元素,您只需要一个UI线程Realm和一个绑定了RealmResults
的{{1}}。
RealmChangeListener
答案 1 :(得分:1)
除了EpicPandaForces答案之外,还可以针对此问题采用快速解决方法:
在findAll()
块中使用简单的同步查询(如realm.copyFromRealm(results)
)和executeTransactionAsync
- 执行不包含写操作的事务可能不是一个好习惯,但它完成工作而无需更改整个代码。
TLDR;将您的查询和copyFromRealm移动到 executeTransactionAsync 块。
答案 2 :(得分:0)
我认为在Realm中没有标准的方法可以做到这一点。我想在RealmObjectA中创建一个静态函数,如copyToRealmObjectB,它有两个参数,一个是RealmObjectA,另一个是RealmObjectB。并在静态函数中调用setter和getter来进行复制。对不起,但它看起来不是一个正常而合理的要求。为什么不直接使用RealmObject?请参阅realm.io/docs/java/latest/#field-types
答案 3 :(得分:0)
我使用RxJava Completable
在后台线程中完成此操作
public class RealmCopier {
private String errorLog = "";
public Completable copyTo(Realm realm) {//in my case remote realm on ROS
return Completable.create(emitter -> {
boolean isCopied = copy(realm);
if (!emitter.isDisposed()){
if (isCopied)
emitter.onComplete();
else
emitter.onError(new Throwable(errorLog));
}
});
}
private boolean copy(Realm realm) {
try {
realm.beginTransaction();
realm.insertOrUpdate(getItems(SomeClassA.class));
realm.insertOrUpdate(getItems(SomeClassB.class));
realm.commitTransaction();
}catch(Exception e){
realm.cancelTransaction();
errorLog = e.getMessage();
return false;
} finally {
realm.close();
}
return true;
}
private List<? extends RealmObject> getItems(Class<? extends RealmObject> classType) {
RealmConfiguration localConfiguration = ConfigurationManager.createLocalConfiguration();
Realm realm = Realm.getInstance(localConfiguration);//local realm
return realm.where(classType).findAll();
}
}