0

OrmLiteを使っandroid.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened hereて新規で始めると が出ます。Activity

Cursor自身は s を使用していないので、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 にも Builder にも close メソッドがないため、実際にどこで閉じる必要があるのか​​ わかりません。

Activityextendsには 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 に答える