以下代码抛出IllegalStateException,当我尝试关闭领域实例时,我正在错误的线程上访问领域。
当我检查是否在closeRealm()方法中关闭了realm实例时抛出了异常。
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
at io.realm.BaseRealm.isClosed(BaseRealm.java:441)
at io.realm.Realm.isClosed(Realm.java:127)
at com.zeyad.usecases.db.RealmManager.lambda$closeRealm$24(RealmManager.java:309)
at com.zeyad.usecases.db.RealmManager$$Lambda$13.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:746)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.os.HandlerThread.run(HandlerThread.java:61)
我正在尝试实现离线第一种方法,我错过了修复关闭正确线程的领域。这是我的代码,请检查出来,让我知道这是什么问题。或者为了更好看,这里是代码的链接:https://github.com/Zeyad-37/UseCases/blob/api/usecases/src/main/java/com/zeyad/usecases/api/DataService.java
提前致谢。
HandlerThread handlerThread = new HandlerThread("backgroundThread");
Handler backgroundHandler = new Handler(handlerThread.getLooper());
public void getUsersOfflineFirst() {
Observable<List> online = restApi.users().doOnNext(user -> {
Realm realm = Realm.getDefaultInstance();
try {
realm.copyToRealmOrUpdate(user)));
} finally {
closeRealm(realm);
}
});
return Observable.defer(() -> {
Realm realm2 = Realm.getDefaultInstance();
return realm2.where(User.class).findAll().asObservable()
.filter(results -> ((RealmResults) results).isLoaded())
.map(users -> realm2.copyFromRealm((RealmResults) users))
.doOnUnsubscribe(() -> closeRealm(realm2));
}).flatMap(new Func1<List, Observable<List>>() {
@Override
public Observable<List> call(List list) {
if (!list.isEmpty())
return Observable.just(list);
else return online;
}
}).compose(applySchedulers());
}
private void closeRealm(Realm realm) {
backgroundHandler.post(() -> {
if (!realm.isClosed()) {
realm.close();
Log.d(RealmManager.class.getSimpleName(), "realm instance closed!");
}
});
}
private <T> Observable.Transformer<T, T> applySchedulers() {
if (!handlerThread.isAlive())
handlerThread.start();
Scheduler backgroundThread = AndroidSchedulers.from(handlerThread.getLooper());
return observable -> observable.subscribeOn(backgroundThread)
.observeOn(AndroidSchedulers.mainThread())
.unsubscribeOn(backgroundThread);
}
答案 0 :(得分:0)
问题可能不是关闭,而是开放。
打开和关闭Realm
实例都应该在同一个线程中发生,就像在Realm中一样,你必须访问同一线程上的Realm对象,如果它不重要的话关闭/打开但对Realm对象的任何操作,正如文档所说:
Realm,RealmObject或RealmResults实例无法传递 线程
我的猜测是online
Observable
你打开 Realm实例不在处理程序线程(Realm realm = Realm.getDefaultInstance();
)上,而所有关闭都发生了在后台处理程序线程。
这是因为你online
Observable
是flatMapped并且没有Scheduler
适用于它。因此虽然源Observable
(Observable.defer()
)确实在后台线程中按需要订阅,但是在线将在调用getUsersOfflineFirst()
方法的线程上订阅,该方法可能不是后台线程。