2

このディスカッションで説明されている問題と同様の問題があります。基になるデータベースが変更されたときに ListView を更新する必要がありますが、クエリは高価であるため、AsyncTask で実行しています。

更新された Cursor の準備ができたら、次のようにします。(これは、起動時にリストが最初に入力される方法でもあります。)

@Override
protected void onPostExecute(Cursor result) {
    if (activity != null) {
        if (currentCursor != null) {
            // existing cursor is closed by adapter.changeCursor() so
            // we don't need to explicitly close it here 
            stopManagingCursor(currentCursor);
        }
        currentCursor = result;
        startManagingCursor(currentCursor);

        if (adapter == null) {
            adapter = getAdapter(result);
            setListAdapter(adapter);
        } else {
            adapter.changeCursor(result);
        }

        activity.onGotList(result, dbAdapter);
    }
}

これが私が得るエラーです。毎回発生するわけではなく、さらにイライラします。

Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: SELECT DISTINCT   t._id AS _id,   t.amount,   t.date,   t.memo,   t.synced,   t.flag,   (children.pa
android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
     at android.database.sqlite.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62)
     at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:100)
     at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:46)
     at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:53)
     at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1412)
     at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1382)

したがって、明らかにカーソルを正しく閉じていません。currentCursor.close()発信カーソルが によって閉じられていることに依存する代わりに呼び出すとadapter.changeCursor()、カーソルを 2 回閉じるか、カーソルを閉じることに関する警告が表示されますnull

これを行う正しい方法は何ですか?

私がリンクしたディスカッションでは、Dianne Hackborn がLoader代わりに a を使用することを提案しています。私のコードは Android 2.1 で実行する必要があるため、これはオプションではありません。

4

3 に答える 3

0

他に何も変更していない場合、リストから再描画するには、カーソルをまったく変更する必要があります。現在のアダプターが必要なだけで済むでしょうか。

の線に沿った何か

adapter.getCursor().requery();

ただし、メインのUIスレッド以外のスレッドにいる場合は、それを呼び出すことができます

//Did not realize this was deprecated Thanks to Graham Borland for the heads up
runOnUiThread(new Runnable(){
    public void run(){
        adapter.getCursor().requery();
    }
});

セットアップに応じて。

新しいソリューションはまだテストが必要であり、明らかに startManaginCursor と stopManaginCursor も非推奨であるため、問題が発生しないことを確認する必要があるため、このソリューションも価値がありません。

stopManagingCursor(adapter.getCursor());
if (!adapter.getCursor().isClosed()) 
    adapter.getCursor().close();
//cursor creation stuff here if needed
startManagingCursor(newCursor);
adapter.changeCursor(newCursor);
于 2011-11-14T21:57:14.150 に答える
0

アクティビティが一時停止または終了したときに、カーソルを .close() してみてください。アクティビティの onPause() または onDestroy() セクション。

于 2011-11-14T21:38:03.533 に答える
0

基本的に、2 つの異なるヘルパーから同じデータベースにアクセスすることは可能ですが、非常に悪い習慣です。そのため、データベース クエリを実行するアクティビティがある場合は、それにアクセスするスレッドも持つべきではありません。そうしないと、android は logcat で静かなエラーをスローします。 、そしてクエリを忘れます...

私が見つけた最善の解決策は、ランナブルのスレッド プールを実装することです。それぞれがデータベース クエリであり、それらはすべて同じデータベース ヘルパーを使用します。したがって、一度に 1 つのスレッドのみがデータベースにアクセスし、データベースはスレッド プールの開始/停止時に開かれ、閉じられます。

スレッド プール パターンの実装は、http: //mindtherobot.com/blog/159/android-guts-intro-to-loopers-and-handlers/にあります。

于 2011-11-14T21:51:02.763 に答える