java.lang.illegalStateException:既に閉鎖されているオブジェクトの再開を試みます
-
29-10-2019 - |
質問
私は、なぜ私が時々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);
}
}
}