使用OrmLite启动新的android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here时得到Activity

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

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都没有任何close方法,因此我不确定实际上应该在哪里关闭。

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

最佳答案

因此,经过一番往复之后,事实证明这是一个没有关闭的惰性集合上的数据迭代器的问题。 @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;
}


有时会发生此问题。 documentation for iterators是明确的。报价:


  注意:您必须浏览所有项目,迭代器才能关闭基础SQL对象。如果您没有完全解决问题,垃圾收集器将在一段时间后关闭SQL语句,这被认为是错误的形式。请参见下面的包装的迭代器。


lazy collections的问题也已记录在案:


  警告:由于我们在关闭迭代器时需要小心,因此最不应该使用for(;;)循环。


为了调试此问题,我们首先使用@ForeignCollection(eager = true)将延迟加载的集合转换为一个渴望的集合。这就消除了表明可能不是从for循环或其他一些不良模式中突围的问题。

对他人的好教训。

07-24 09:49
查看更多