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

时间:2017-05-10 01:07:07

标签: android realm rx-java

以下代码抛出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);
}

1 个答案:

答案 0 :(得分:0)

问题可能不是关闭,而是开放。
打开和关闭Realm实例都应该在同一个线程中发生,就像在Realm中一样,你必须访问同一线程上的Realm对象,如果它不重要的话关闭/打开但对Realm对象的任何操作,正如文档所说:

  

Realm,RealmObject或RealmResults实例无法传递   线程

我的猜测是online Observable打开 Realm实例不在处理程序线程(Realm realm = Realm.getDefaultInstance();)上,而所有关闭都发生了在后台处理程序线程。

这是因为你online Observable是flatMapped并且没有Scheduler适用于它。因此虽然源ObservableObservable.defer())确实在后台线程中按需要订阅,但是在线将在调用getUsersOfflineFirst()方法的线程上订阅,该方法可能不是后台线程。