3

時々IllegalStateExceptionが発生する理由を理解しようとしています。スレッドを使用してリストをロードし、SQLiteデータベースにクエリを実行する方法を示す良い例が見つかりません。以下に私のコードを含めました。ほとんどの場合は正しく機能しますが、IllegalStateExceptionが発生する場合があります。

また、ExpandableListActivityのインスタンスである私の別のアクティビティでも同様の例外が発生しました。その例外は、「すでに閉じられているカーソルを再クエリしようとしている」ことを示しています。

エラーが発生しないように、誰かがこれを行う正しい方法を教えてもらえますか?すべてのデータをメモリにコピーするのではなく、カーソルを使用したいと思います。これがわからない場合は、すべてをメモリにロードする必要があります。

この問題は、startManagingCursor(Cursor)と、onDestroy()でデータベース接続が閉じられているという事実に関係していると思います。plzヘルプ
-物語

public class MyListActivity extends ListActivity {
    private MyCursorAdapter adapter;
    private SQLiteDatabase db = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        try {
            new RetrieveCursorTask(this).execute((Void[]) null);
        } catch (Exception e) {
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // Null out the cursor. 
        if (adapter != null) {
            adapter.changeCursor(null);
            adapter = null;
        }

        if (db != null && db.isOpen()) {
            db.close();
        }
    }

    private class RetrieveCursorTask extends AsyncTask<Void, Void, Cursor> {
        private Context ctx;

        public RetrieveCursorTask(Context ctx) {
            this.ctx = ctx;
        }

        @Override
        protected Cursor doInBackground(Void... params) {
            Cursor cursor = null;
            DbHelper helper = new DbHelper(ctx);

            try {
                db = helper.getReadableDatabase();
                cursor = db.query("users",
                    new String[] {
                        DbHelper.ID_COLUMN,
                        DbHelper.UID_COLUMN
                    }, 
                    null, null, null, null, null);
                startManagingCursor(cursor);
            } catch (Exception e) {
            }
            return cursor;
        }

        @Override
        protected void onPostExecute(Cursor cursor) {
            super.onPostExecute(cursor);

            if (cursor != null) {
                try {
                    adapter = new MyCursorAdapter(ctx, cursor);
                } catch (Exception e) {
                }
                setListAdapter(adapter);
            } 
        }
    }

    private class MyCursorAdapter extends CursorAdapter {
        private Context ctx;

        public MyCursorAdapter(Context context, Cursor c) {
            super(context, c);
            this.ctx = context;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            // ...
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            // ...
        }
    }
}
4

2 に答える 2

4

希望する方法でDBにクエリを実行する場合は、 AsyncQueryHandlerを調べてください。

タスクRetrieveCursorTaskは別のスレッドで実行されているため、アクティビティが破棄されてもAsyncTaskはバックグラウンドで実行されている可能性がありますが、メインアクティビティonDestroyでカーソルを閉じると、AsyncTaskが戻った後に再度クエリされる場合があります。

于 2011-06-18T06:10:43.393 に答える
0

onPostExecuteでアダプタを設定したブロックを同期する必要があるようです。問題は、AsyncTaskが別のスレッドで実行されているため、カーソルが設定され、その後要求される順序が保証されないことです。これを試して..

    @Override
    protected void onPostExecute(Cursor cursor) {
        super.onPostExecute(cursor);

        synchronized(anyObject) {
        if (cursor != null) {
            try {
                adapter = new MyCursorAdapter(ctx, cursor);
            } catch (Exception e) {
            }
            setListAdapter(adapter);
        } 
        }
    }
于 2011-08-12T12:49:42.600 に答える