我在项目中使用了RealmObjects
class A extends RealmObject {
...
private B b;
private RealmList<C> c;
//Getter and Setters
}
class B extends RealmObject {
...
private RealmList<D> d;
//Getter and Setters
}
class C extends RealmObject {
...
private String str1;
private String str2;
//Getter and Setter
}
class D extends RealmObject {
...
private String str1;
private String str2;
//Getter and Setter
}
我从Realm获得了A
的列表,如下所示:
Realm.where(A.class).findAllSortedAsync("sortField", Sort.DESCENDING)
.asObservable().filter(items -> items.isLoaded())
.map(new Func1<RealmResults<A>, List<A>>() {
@Override
public List<A> call(RealmResults<A> realmResults) {
return Realm.copyFromRealm(realmResults);
}
})
.observeOn(Schedulers.computation())
.map(new Func1<List<A>, Object object>() {
@Override
public Object call(List<A> items) {
for (A item : items) {
item.get(...);
item.set(...);
}
}
}).observeOn(AndroidSchedulers.mainThread()).subscribe(...);
当我运行上面的代码时,抛出以下异常:
FATAL EXCEPTION: RxComputationScheduler-2
java.lang.IllegalStateException: Fatal Exception thrown on Scheduler.Worker thread.
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
at io.realm.BaseRealm.checkIfValid(BaseRealm.java:353)
at io.realm.RealmResults.checkForAddRemoveListener(RealmResults.java:138)
at io.realm.RealmResults.removeChangeListener(RealmResults.java:171)
at io.realm.rx.RealmObservableFactory$6$2.call(RealmObservableFactory.java:156)
at rx.subscriptions.BooleanSubscription.unsubscribe(BooleanSubscription.java:71)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)
at rx.Subscriber.unsubscribe(Subscriber.java:98)
at rx.internal.operators.OnSubscribeMap$MapSubscriber.onNext(OnSubscribeMap.java:72)
at rx.internal.operators.OperatorObserveOn$ObserveOnSubscriber.call(OperatorObserveOn.java:224)
at rx.internal.schedulers.EventLoopsScheduler$EventLoopWorker$1.call(EventLoopsScheduler.java:172)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:272)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
看到如何在计算线程上抛出异常,我想当我尝试访问A
类的对象时会发生这种情况。我不明白这是怎么发生的,因为我已经将托管的RealmResults转换为非托管List,因此在其他线程中访问它应该不是Realm wiki中提到的问题。
非托管对象就像普通的Java对象一样,它们不会被持久化,也不会自动更新。它们可以在线程之间自由移动。
我的问题是如何从RealmResults获取一个非托管的对象列表,这些对象可以从其他线程访问,以及我在上面的实现中做错了什么?
答案 0 :(得分:1)
你错过了
}).observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(AndroidSchedulers.mainThread()) // this
.subscribe(...);
虽然考虑到你是在UI线程上复制你的结果,但是当我找到键盘时,我可能会更多地考虑这个问题。
编辑:好的,我认为应该这样工作:
realm.where(A.class).findAllAsync()
.asObservable()
.subscribeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(AndroidSchedulers.mainThread())
.observeOn(Schedulers.io())
.map(new Func1<RealmResults<A>, List<A>>() {
@Override
public List<A> call(RealmResults<A> ignored) {
try(Realm bgRealm = Realm.getDefaultInstance()) {
return bgRealm.copyFromRealm(
bgRealm.where(A.class).findAllSorted("sortField", Sort.DESCENDING)
);
}
}
})
.observeOn(Schedulers.computation())
.map(new Func1<List<A>, Object>() {
@Override
public Object call(List<A> items) {
for (A item : items) {
item.get(...);
item.set(...);
}
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(...);
答案 1 :(得分:0)
使用方法Realm.where(A.class).findAllSortedAsync("sortField", Sort.DESCENDING)
,这将在主线程中发生。
使用方法map ... return Realm.copyFromRealm(realmResults);
,Rx将在另一个线程中运行map方法,因此会发生错误:
Realm从错误的线程访问。只能访问领域对象 在他们创建的主题上。
如果你想在另一个线程中运行,你可以通过在该线程中创建另一个Realm实例来解决这个问题
map(new Func1<RealmResults<A>, List<A>>() {
@Override
public List<A> call(RealmResults<A> realmResults) {
Realm realm = Realm.getDefaultInstance();
try {
realm.beginTransaction();
// Your code here
realm.commitTransaction();
} finally {
realm.close();
}
}
})