【问题标题】:Realm instance has already been closed - with RxJava2领域实例已经关闭 - 使用 RxJava2
【发布时间】:2018-03-03 16:43:12
【问题描述】:

我以这种方式将 Realm 与 RxJava 结合使用:

public Flowable<List<EventEntity>> getAll() {
  try (final Realm realm = Realm.getInstance(mRealmConfiguration)) {
    RealmQuery<RealmEvent> query = realm.where(RealmEvent.class);
    Flowable<RealmResults<RealmEvent>> result;
    if (realm.isAutoRefresh()) {
       result = query
       .findAllAsync()
       .asFlowable()
       .filter(RealmResults::isLoaded);
    } else {
      result = Flowable.just(query.findAll());
    }
    return result
      .unsubscribeOn(AndroidSchedulers.mainThread());
  }
}

我在应用程序的多个位置使用此链。例如:

return Observable.merge(
      mEventRepository.getAll()
        .toObservable(),
      subjectNotificationChange
        .flatMapMaybe(notification ->
          mEventRepository.getAll()
            .firstElement()
        )
    )

问题是我得到异常:java.lang.IllegalStateException: This Realm instance has already been closed,使其无法使用。

我查看了 RealmObservableFactory 的实现方法,每次调用 subscribe 方法都应该创建新的 Realm 实例。整个情况看起来都是引用计数的问题。

你知道问题出在哪里吗?

【问题讨论】:

  • 您是否在其他任何地方手动拨打realm.close()
  • 没有。当我省略对资源的尝试时,一切都可以正常工作。
  • 这对我来说真的很奇怪,因为根据代码,我希望它能够工作...... :(
  • 好的,等等,等等。您确定您没有在后台线程上收到该错误吗?因为如果 Realm 在没有为线程打开其他实例的情况下关闭,.just() 端将无法工作。
  • 添加异常堆栈跟踪可能会有所帮助。

标签: android realm rx-java2


【解决方案1】:

Java 的 try-with-resource在您离开代码块后立即关闭资源,但 RxJava 是 惰性 等等,只有在您实际订阅时才开始工作,这种情况会发生在您的代码退出getAll() 函数之后。

编辑:由于您每次都构建一个特殊的 Realm 实例,并将配置传递给它,因此该实例不会共享,因此每次都会最终关闭。

相反,使用Realm.setDefaultConfiguration(config) 更早地初始化您的Realm。然后,在您的函数中使用Realm.getDefaultInstance(),这样您就可以访问默认的共享实例,而不是每次都创建一个新实例。

Edit2:最简单的解决方案是保留对Realm 实例的引用:

class MyRepository {

    private final Realm realm;

    public MyRepository(Realm realm) {
        this.realm = realm;
    }

    public Flowable<List<EventEntity>> getAll() {
        RealmQuery<RealmEvent> query = realm.where(RealmEvent.class);
        // ...
    }

}

Realm realm = Realm.getDefaultInstance();
MyRepository repository = MyRepository(realm);
repository.getAll()
// ...

【讨论】:

  • 是的,但是subscribe方法的实现又调用了Realm的getInstance方法。当 Realm 实例关闭时 RealmResult 被销毁?
  • @elnino 对不起,如果我不够清楚。您请求一个Realm 实例,准备一个Flowable 并返回它。问题是当你返回它时,Realm 实例被try-with 关闭。因此,当您稍后订阅时,您已关闭且不再有效的初始 Realm 引用。是的,当您关闭实例时,来自 Realm 实例的结果将失效。
  • 我在 Realm 的官方页面上看到了这个解决方案(尝试使用资源)。在页面底部。 academy.realm.io/posts/…使用defer可以解决这个问题吗?可以在 Realm 自动关闭之前创建和订阅对象。还是在不关闭实例的情况下使用 Realm 更好的解决方案?
  • @elnino 我想我现在看到了问题:您正在创建一个特殊的 Realm 实例,将配置传递给它,而不是请求默认实例。尝试使用 Realm.setDefaultConfiguration(config) 配置您的 Realm 并在您的代码中使用 getDefaultInstance()
  • 我使用了 getDefaultInstance 但结果是一样的,
【解决方案2】:

我找到了解决方案。这是官方示例中的错误。当您调用提到的链时,必须存在同一线程的其他打开的 Realm 实例。在其他情况下,RealmResult 无效。可以使用 ESala 提到的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多