我正在试图弄清楚为什么我偶尔会遇到IllegalStateException。我找不到任何好的示例来说明如何使用线程加载列表来查询SQLite数据库。我在下面提供了我的代码。大部分时间它都能正常工作,但偶尔也会出现IllegalStateException。
我在我的另一个活动中也得到了一个类似的例外,它是ExpandableListActivity的一个实例。该异常说明“试图重新查询已经关闭的游标”。
有人能告诉我这样做的正确方法,以免造成任何错误吗?我更喜欢使用游标而不是将所有数据复制到内存中。如果我无法解决这个问题,那么我将把它全部加载到内存中。
我认为这个问题与startManagingCursor(Cursor)有关,而且在onDestroy()中关闭了数据库连接。 请帮忙 - 故事
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) {
// ...
}
}
}
答案 0 :(得分:4)
如果您想以您想要的方式查询数据库,请查看AsyncQueryHandler。
您的任务RetrieveCursorTask正在单独的线程上运行,因此当您的活动被销毁时,您的AsyncTask可能仍在后台运行,但是当您在主活动onDestroy中关闭光标时,可能会在您的AsyncTask返回后再次重新获取它。
答案 1 :(得分: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);
}
}
}