【问题标题】:This Realm instance has already been closed, making it unusable + RxJava这个 Realm 实例已经被关闭,使其无法使用 + RxJava
【发布时间】:2017-01-03 16:23:20
【问题描述】:

首先我通过 Repository 类管理领域实例:

public class RealmRepository {

private Lock lock;

protected RealmRepository() {
    lock = new ReentrantLock();
}

public  <T> T execute(Executor<T> executor) {
    Realm realm = null;
    try {
        lock.lock();
        realm = Realm.getDefaultInstance();
        return executor.execute(realm);
    } finally {
        if (realm != null && !realm.isClosed()) {
            realm.close();
        }
        lock.unlock();
    }
}

public interface Executor<T> {
    T execute(Realm realm);
}
}

并且唯一由这个 RealmRepository 扩展的类,这是我的控制器类。 问题是当我第一次在我得到的片段中执行方法时:

java.lang.IllegalStateException: 这个 Realm 实例已经关闭,无法使用。

但在此错误之后,如果重新加载片段一切正常。在这第一个片段执行从服务类调用的方法之前,它运行良好。 例如: 此方法即使在第一次执行时也能完美运行:

public Observable<ModuleRealm> getModule(String moduleTitle) {
    return execute(realm -> realm.where(ModuleRealm.class)
            .equalTo("code", moduleTitle)
            .findAllAsync()
            .asObservable()
            .first()
            .map(RealmResults::first));
}

但是这个抛出异常:

public Observable<List<ProductCategoryRealm>> getProductCategories() {
    return execute(realm -> realm.where(ProductCategoryRealm.class)
            .findAll()
            .asObservable()
            .first()
            .map(realm::copyFromRealm));
}

【问题讨论】:

    标签: android realm


    【解决方案1】:

    Realm 实例在初始初始化调用后进行引用计数。每次调用 close() 都会减少这个引用计数,每次调用 getDefaultInstance() 都会增加这个引用计数。一旦引用计数达到 0,Realm 的资源就会被释放。

    考虑到您使用 Lock 来阻止对 Realm 实例的访问,当您调用 close() 时会导致引用计数达到 0,然后在 Realm 已释放后不会重新初始化 Realm 配置它的资源。

    为了解决这个问题,您需要在随后调用 close() 之前对 getDefaultInstance() 的调用进行重叠,以确保在您仍在积极使用 Realm 时您的引用计数保持 > 0,否则您需要重新初始化每次都会影响整个 Realm 配置。

    【讨论】:

    • 我如何跟踪剩余 = 0?
    • 写一个RealmWrapper类:P
    • @Submersed 你100%确定你的结论吗?我简直不敢相信零引用使 Realm 在下一次 init() 调用之前关闭。是的,它可能会导致清除所有缓存的数据,但是调用 getDefaultInstance() 应该自己再次初始化它,不是吗?
    • 不,据我所知,这种方式行不通。源代码可用,随时进入。
    • 如果 Realm 完全关闭然后重新打开,则会重新初始化。关闭 Realm 中所有之前的 RealmResults 都将失效。
    【解决方案2】:

    在这种情况下,finally 方法将在调用方法得到结果之前执行。

    【讨论】:

      【解决方案3】:

      Realm 实例可以用 try with resource 来初始化。你可以使用

      try (Realm realm = Realm.getDefaultInstance()){
          realm.beginTransaction();
          // your queries
          realm.commitTransaction();
      }
      

      Realm 实例实现了 Closable 接口,允许您忽略正在运行的实例的数量。

      【讨论】:

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