Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/198.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 我无法在正确的线程上关闭我的领域实例_Android_Realm_Rx Java - Fatal编程技术网

Android 我无法在正确的线程上关闭我的领域实例

Android 我无法在正确的线程上关闭我的领域实例,android,realm,rx-java,Android,Realm,Rx Java,下面的代码抛出一个IllegalStateException,即当我试图关闭领域实例时,我在错误的线程上访问领域 当我在closeRealm()方法中检查领域实例是否已关闭时,会引发异常 我正在尝试实现脱机第一种方法,但我缺少在正确的线程上修复域关闭。这是我的代码,请检查一下,让我知道是什么问题。或者,为了更好地查看,这里有一个代码链接: 提前谢谢 HandlerThread handlerThread = new HandlerThread("backgroundThread"); Handl

下面的代码抛出一个IllegalStateException,即当我试图关闭领域实例时,我在错误的线程上访问领域

当我在closeRealm()方法中检查领域实例是否已关闭时,会引发异常

我正在尝试实现脱机第一种方法,但我缺少在正确的线程上修复域关闭。这是我的代码,请检查一下,让我知道是什么问题。或者,为了更好地查看,这里有一个代码链接:

提前谢谢

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);
}