0

当我开始使用 OrmLiteandroid.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here开始一个新的时,我得到了一个。Activity

Cursor自己没有使用任何 s,所以它必须是 ORMLite 使用的低级代码。不确定这里的相关代码是什么,但基本上我在事务管理器中使用 Query/DeleteBuilders 和 2 个 Dao 对象。导致问题的最小示例(删除了异常处理):

return new TransactionManager(connectionSource).callInTransaction(new Callable<List<ConversionData>>() {
    public List<ConversionData> call() throws Exception {
        QueryBuilder<ConversionData, Date> builder = getDataDao().queryBuilder();
        builder.orderBy("date", /* desc */ true);
        return builder.query();
    }
});

由于 Dao 和 Builders 都没有任何关闭方法,我不确定我应该在哪里实际关闭。

Activity的扩展中有一个 close 方法OrmLiteBaseActivity,但是当我从其他活动返回时,我将如何再次打开它?

4

1 回答 1

3

因此,经过一番反复,结果证明这是一个未关闭的惰性集合上的数据迭代器的问题。@Voo 正在做类似以下的事情:

for (ConversionRate rate : conversionRates) { 
    if (rate.getCurrency().equals(curr)) 
        // you can't do this because otherwise the iterator won't be closed
        return rate; 
}

这个问题偶尔会发生。迭代器的文档对此很明确。去引用:

注意:您必须对迭代器的所有项目进行分页才能关闭基础 SQL 对象。如果你不一直走,垃圾收集器将在一段时间后关闭 SQL 语句,这被认为是错误的形式。请参阅下面的包装迭代。

还记录了惰性集合的问题:

警告:这里很可能不应该使用 for(;;) 循环,因为我们需要小心关闭迭代器。

为了调试这个问题,我们首先将延迟加载的集合变成了一个带有@ForeignCollection(eager = true). 这消除了表明它可能是不正确的for循环中断或其他一些错误模式的问题。

给别人很好的教训。

于 2012-04-23T21:19:46.233 回答