Android 我无法在正确的线程上关闭我的领域实例
下面的代码抛出一个IllegalStateException,即当我试图关闭领域实例时,我在错误的线程上访问领域 当我在closeRealm()方法中检查领域实例是否已关闭时,会引发异常 我正在尝试实现脱机第一种方法,但我缺少在正确的线程上修复域关闭。这是我的代码,请检查一下,让我知道是什么问题。或者,为了更好地查看,这里有一个代码链接: 提前谢谢Android 我无法在正确的线程上关闭我的领域实例,android,realm,rx-java,Android,Realm,Rx Java,下面的代码抛出一个IllegalStateException,即当我试图关闭领域实例时,我在错误的线程上访问领域 当我在closeRealm()方法中检查领域实例是否已关闭时,会引发异常 我正在尝试实现脱机第一种方法,但我缺少在正确的线程上修复域关闭。这是我的代码,请检查一下,让我知道是什么问题。或者,为了更好地查看,这里有一个代码链接: 提前谢谢 HandlerThread handlerThread = new HandlerThread("backgroundThread"); Handl
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);
}
HandlerThread HandlerThread=新的HandlerThread(“背景线程”);
Handler backgroundHandler=新处理程序(handlerThread.getLooper());
public void getUsersOfflineFirst(){
Observable online=restApi.users().doOnNext(用户->{
Realm Realm=Realm.getDefaultInstance();
试一试{
realm.copyToRealmOrUpdate(用户));
}最后{
封闭领域(领域);
}
});
返回可观察。延迟(()->{
Realm realm2=Realm.getDefaultInstance();
返回realm2.where(User.class).findAll().asObservable()
.filter(结果->((RealmResults)结果).isLoaded())
.map(用户->realm2.copyFromRealm((RealmResults)用户))
.dounsubscribe(()->closeRealm(realm2));
}).flatMap(新函数1(){
@凌驾
公共可观察呼叫(列表){
如果(!list.isEmpty())
返回可观察的。刚(列表);
否则在线返回;
}
}).compose(applySchedulers());
}
私有领域(领域领域){
backgroundHandler.post(()->{
如果(!realm.isClosed()){
realm.close();
Log.d(RealmManager.class.getSimpleName(),“领域实例已关闭!”);
}
});
}
私有可观察。Transformer applySchedulers(){
如果(!handlerThread.isAlive())
handlerThread.start();
Scheduler backgroundThread=AndroidSchedulers.from(handlerThread.getLooper());
返回observable->observable.subscribeOn(后台线程)
.observeOn(AndroidSchedulers.mainThread())
.取消订阅(背景线程);
}
问题可能不在于关闭,而在于打开。打开和关闭
Realm
实例都应该在同一个线程上进行,就像在Realm中一样,您必须访问同一线程上的Realm对象,这与是否关闭/打开无关,但与Realm对象上的任何操作无关,如文档所述:
无法传递Realm、RealmObject或RealmResults实例
线程
我的猜测是,在在线
可观察
上,您正在打开的领域实例不在处理程序线程上(Realm Realm=Realm.getDefaultInstance();
),而所有关闭都发生在后台处理程序线程上
发生这种情况是因为
联机
可观察
是平面映射的,并且没有调度程序
应用于它。因此,尽管源Observable
(Observable.defer()
)确实按照需要在后台线程中订阅,但在线服务将在调用getusersoffrinfirst()的线程中订阅
方法,该方法可能不是后台线程。整个堆栈跟踪而不仅仅是错误消息将有助于缩小其范围。我添加了完整的堆栈跟踪。您是对的,这一点都没有帮助!:不管怎样,我只是认为你发布到的后台处理程序不是你的线程。您可能需要使用subscribeOn(AndroidSchedulers.from(handlerThread.getLooper())
,并且不要忘记在同一个调度程序上执行unsubscribe
。您能解释一下“我只是认为您发布到的后台处理程序不是您拥有该线程的线程”是什么意思吗我的意思是你打开了这个领域,这是一个输入错误:p但是当我试图关闭这个实例时会抛出异常。我在问题中添加了完整的堆栈跟踪,编辑了答案以添加更多信息。它会在关闭时出现,因为打开没有问题,而关闭是你在其他线程上执行的另一个操作,你可以创建一个从任何线程中删除Realm对象,限制是您可以在线程之间传递Realm对象,正如我所写的,您似乎在不同的线程中打开它,然后关闭它,所以您在线程之间传递它。您可以尝试添加subscribeOn(AndroidSchedulers.from(handlerThread.getLooper())
到联机Observable
以查看它是否解决了问题,还可以将日志添加到您触摸领域对象的所有位置,以查看它在哪个线程上执行了操作以发现问题。我发现问题出在代码的其他地方:)我记录了领域实例打开和关闭的位置,然后我可以轻松修复它
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);
}