使用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
循环或其他一些不良模式中突围的问题。对他人的好教训。