记得在所有Realm实例上调用close(),即使我调用close()

时间:2016-05-19 21:21:47

标签: java android realm

我正在看

Remember to call close() on all Realm instances. Realm /data/data/com.org.example/files/default.realm is being finalized without being closed, this can lead to running out of native memory. 

即使我在.close()的每次通话后都清楚地拨打了getInstance(realmConfig)

大部分时间看起来像这样:

Realm realm = Realm.getInstance(realmConfig);
try {
    realm.beginTransaction();
    realm.copyToRealmOrUpdate(someData);
    realm.commitTransaction();
} catch (Exception e) {
    realm.cancelTransaction();
} finally {
    if (realm != null) {
        realm.close();
    }
}

其他时候看起来像(使用Rx Observable Pattern):

@Override
public void call(Subscriber<? super JsonElement> subscriber) {
    SomeJson someJson = Realm.getInstance(mRealmConfig).where(SomeJson.class)
                    .equalTo("type", type)
                    .equalTo("id", id)
                    .findFirst();

    if (someJson == null || !someJson.isDataValid()) {
        Logger.d(TAG, "Did not find value for id: " + id + " for type: " + type);
        subscriber.onNext(null);
        subscriber.onCompleted();
        Realm.getInstance(mRealmConfig).close();
        return;
    }

    JsonElement val = (new JsonParser()).parse(someJson.jsonString);
    subscriber.onNext(val);
    subscriber.onCompleted();
    Realm.getInstance(mRealmConfig).close();
}

知道我为什么还会收到这些警告?

2 个答案:

答案 0 :(得分:6)

Realm realm = Realm.getInstance(mRealmConfig);
// ...
Realm.getInstance(mRealmConfig).close();

问题出在这里。您已获得其他 Realm并关闭它,但您尚未关闭orignal realm

你应该对所有这些使用try-with-resources:

try (Realm realm = Realm.getInstance(realmConfig)) {
    realm.beginTransaction();
    realm.copyToRealmOrUpdate(someData);
    realm.commitTransaction();
} catch (Exception e) {
    realm.cancelTransaction();
}

[请注意,realm在您测试时永远不会为空,如果是,它会更快地触发NPE。]

@Override
public void call(Subscriber<? super JsonElement> subscriber) {
    try (Realm realm = Realm.getInstance(mRealmConfig)) {
        SomeJson someJson = realm.where(SomeJson.class)
                    .equalTo("type", type)
                    .equalTo("id", id)
                    .findFirst();

        if (someJson == null || !someJson.isDataValid()) {
            Logger.d(TAG, "Did not find value for id: " + id + " for type: " + type);
            subscriber.onNext(null);
            subscriber.onCompleted();
            return;
        }

        JsonElement val = (new JsonParser()).parse(someJson.jsonString);
        subscriber.onNext(val);
        subscriber.onCompleted();
    }
}

答案 1 :(得分:4)

每次调用Realm.getInstance(mRealmConfig)时,都会在当前线程中创建对此Realm实例的本地引用。

您需要在所有引用上调用close()才能真正关闭Realm实例。

在您的Rx实现中,您调用Realm.getInstance(mRealmConfig)三次,因此创建了三个本地引用,其中两个已关闭。

您可以创建一个引用并一劳永逸地关闭它(就像您在第一个代码段中所做的那样)

@Override
public void call(Subscriber<? super JsonElement> subscriber) {
    Realm realm = Realm.getInstance(mRealmConfig);
    SomeJson someJson = realm.where(SomeJson.class)
                    .equalTo("type", type)
                    .equalTo("id", id)
                    .findFirst();

    if (someJson == null || !someJson.isDataValid()) {
        Logger.d(TAG, "Did not find value for id: " + id + " for type: " + type);
        subscriber.onNext(null);
        subscriber.onCompleted();
        realm.close();
        return;
    }

    JsonElement val = (new JsonParser()).parse(someJson.jsonString);
    subscriber.onNext(val);
    subscriber.onCompleted();
    realm.close();
}