web-dev-qa-db-ja.com

非アクティブ化されていないか、致命的でないエラーを閉じていないカーソルをファイナライズする

このコードで「無効化または閉じられていないカーソルの最終処理」エラーが表示されます。コードはリストビューを埋めるために使用されます。

それは致命的ではないエラーなので、クラッシュはなく、すべて正常に動作するようです。しかし、私はエラーが好きではありません。

このコードの最後でカーソルを閉じると、リストビューは空のままになります。 onStopでカーソルを閉じると、同じエラーが発生します。

これを修正するにはどうすればよいですか?

private void updateList() { 
        DBAdapter db = new DBAdapter(this); 
        db.open(); 
            //load all waiting alarm 
            mCursor=db.getTitles("state<2"); 
            setListAdapter(new MyCursorAdapter(this, mCursor)); 
            registerForContextMenu(getListView()); 
            db.close(); 
        } 


error : 


E/Cursor  ( 2318): Finalizing a Cursor that has not been deactivated 
or closed. database = /data/data/xxxxxxxxxxxxxxx.db, table = alerts, 
query = SELECT _id, alert_id, 
E/Cursor  ( 2318): 
Android.database.sqlite.DatabaseObjectNotClosedException: Application 
did not close the cursor or database 
object that was opened here 
E/Cursor  ( 2318):      at 
Android.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.Java:210) 
E/Cursor  ( 2318):      at 
Android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDr­iver.Java: 
53) 
E/Cursor  ( 2318):      at 
Android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.j­ava: 
1345) 
E/Cursor  ( 2318):      at 
Android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.Java­: 
1229) 
.... 
.... 
33
arnold

onStop()またはonDestroy()Cursorを閉じても、そのメッセージは表示されません。もう一度試してください。または、クエリからCursorを取得した後にstartManagingCursor()を呼び出すと、Androidはそれ自体でCursorを閉じます。

27
CommonsWare

スコット、

私はあなたと同じ問題に遭遇しました。データベース、つまり「db.close()」を閉じる前に、まずカーソルが閉じていること、つまり「mCursor.close()」を確認してください

そのようです:

private void updateList()
{ 
    DBAdapter db = new DBAdapter(this);
    db.open();

    //load all waiting alarm
    mCursor=db.getTitles("state<2"); 
    setListAdapter(new MyCursorAdapter(this, mCursor)); 
    registerForContextMenu(getListView()); 

    // Let's close the cursor.
    mCursor.close();
    db.close(); 
} 

カーソルを閉じた場合、リストビューは空のままになると述べました。情報をクラスに渡し、それをコピー(メモリの割り当て)してからカーソルを閉じることをお勧めします。

13
jbaez

クエリがカーソルを返すとき、実際にはカーソルの最初のレコードの「前」に配置されます。アダプタは、最初の要素で「getItem」を実行しようとするため、カーソルがいずれにも位置していないため失敗します。

基本アダプターでは、getViewsでcursorMoveToPositionを実行します。これにより、movefirstが不要になります。

2
Dent

StartManagingCursor()は推奨されるアプローチではなくなったため、使用しないでください。この問題は、ファイナライザがこのオブジェクトに到達するまでにカーソル/ DB接続がまだ閉じられていないために発生します。ローダーでカーソルを管理できるようにするか、すべてのカーソル/ DB/SQLiteOpenHelper接続を自分で追跡してクリーンアップすることで、これを回避できます。

ローダーの使用はかなり面倒であり、リストビューと連動して動作するには多くの可動部品が必要です。一方、カーソルとデータベース接続を追跡すると、人為的エラーが発生しやすくなります。カーソル/ DBオブジェクトの数が少ない場合は、後者のソリューションをお勧めします。そうでない場合は、ローダーに接続を処理させます。

1
Deepak Bala

作成中のカーソルオブジェクトを閉じます。

カーソルオブジェクトを作成し、SQLiteテーブルの走査を完了したら、使用後にそれを閉じます。このカーソルのクローズにより、logcatでの例外が防止されます。

開いたままになっているカーソルのファイナライズに関連する例外は発生しません。

これは私のアプリケーションで同じ問題を修正しました。

1
Master

ちょうど同じ問題があり、あなたに知らせると思った-念のため....

フェッチルーチンを誤って2回呼び出したため、最初の呼び出しの結果のカーソルが "失われました"。これによりエラーが発生しました。

0
user387184

私もカーソルのクローズに問題があります:

  • リストビューのアダプターを設定した直後にカーソルを閉じると、データが表示される前にカーソルが閉じます。

  • カーソルは廃止されているため、startManagingCursorを使用してカーソルを管理することはできません。

  • StartManagingCursorの新しいcursorLoaderの置き換えは過剰であるようです。

  • 提案されたとおりにカーソルの位置を移動しても機能しませんでした。

  • タスクをアクティビティの内部クラスにして、アクティビティのonDestroyメソッドでカーソルを閉じると、常にではなく時々動作します。

  • タスクをアクティビティの内部クラスにし、アクティビティのonStopメソッドでカーソルを閉じることは機能しているようです。

また、カーソルを閉じる前にデータベースとsqliteオープンヘルパーを閉じることができることもわかりました。リストビューのアダプターを設定した直後にそれらを閉じることもできます。データは引き続き表示されます。

0
subduedjoy

startManagingCursor(cursor);

これで問題が解決しました

0
Krishna

この問題に2日間苦労しました。データベースクエリから返されたカーソルをリストアダプターに直接渡すサンプルコードを機能させようとしていました-中間アダプターはありません。 ListAdapterに渡す前にカーソルで 'moveToFirst()'を呼び出すまで、動作を拒否しました-ただ空白の画面を表示しました。フィギュアに行く!これをコメントアウトすると、壊れます。

人々が私と同じ闘争を救うためにこれを共有すると思った。

誰かがこれがなぜそうなのかについていくつかの光を当てることができれば、私はそれを感謝します。カーソルを正しく実行するために、今までカーソルでmoveToFirstを呼び出す必要はありませんでした。

0
birdman