java.lang.illegalStateException:既に閉鎖されているオブジェクトの再開を試みます

StackOverflow https://stackoverflow.com/questions/6393584

質問

私は、なぜ私が時々IllegalStateExceptionを取得しているのかを理解しようとしています。スレッドを使用してリストをロードしてSQLiteデータベースを照会する方法を示す良い例が見つかりません。以下にコードを含めました。ほとんどの場合、それは正しく機能しますが、時には、IllegalStateExceptionを取得しています。

また、私の別のアクティビティで同様の例外を獲得しました。その例外は、「すでに閉じられたカーソルを取り戻そうとしている」と述べています。

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

この問題は、StartManagingCursor(カーソル)と、データベース接続が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) {
            // ...
        }
    }
}
役に立ちましたか?

解決

調べてください AsyncqueryHandler DBを必要に応じてクエリしたい場合。

タスクRetireveCursortaskは個別のスレッドで実行されているため、アクティビティが破壊されると、Asynctaskがバックグラウンドで実行されている可能性がありますが、メインアクティビティでカーソルを閉じていると、Asynctaskが戻ってきた後に再び回復する可能性があります。

他のヒント

Adapterを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);
        } 
        }
    }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top