当你在Cursor对象上调用.close()时,是否意味着在活动的剩余时间内它不能被使用?以下是我的Manager对象中的方法:
Cursor cursor = null;
try {
SQLiteDatabase db = openDb();
cursor = db.query("table", null, "id=?", new String[] { id }, null, null, null);
cursor.moveToFirst();
long dateTime = cursor.getLong(1);
cursor.close();
return dateTime ;
} catch (CursorIndexOutOfBoundsException e) {
return -1;
} finally {
if (cursor != null) {
cursor.close();
}
closeDb();
}
这是给我一个IllegalStateException的方法。但是,有一点点扭曲:它只会在第二次调用时抛出错误。跟踪堆栈跟踪,我发现导致我麻烦的行如下:
Cursor cursor = db.query("table", null, "id=?", new String[] { id }, null, null, null);
只是为了清楚一点,通过单击特定的ListView项,可以在Activity的生命周期内多次调用此方法。 openDb()和closeDb()方法如下:
public SQLiteDatabase openDb() {
if (mDbHelper == null) {
mDbHelper = new DatabaseHelper(mContext);
}
return mDbHelper.getWritableDatabase();
}
public void closeDb() {
mDbHelper.close();
}
这些存储在Manager对象的超类中。 mDbHelper是一个静态对象。
作为Android编程的新手,我想知道为什么这会让我异常。我能想到的唯一合乎逻辑的解释是Cursor Objects实际上是被重用的,它们不应该在活动期间关闭。我对吗?如果我是,你什么时候关闭光标呢?
--- --- EDIT
稍微修改了代码,我似乎得到了一个更加不规则的异常。由于一些奇怪的原因,它似乎是随机发生的;我可以点击八个多个ListView项目,没有任何问题,突然bam!第九个导致应用程序崩溃。
因为单击ListView也会调用一个更新同一个表的方法(到目前为止,这个方法到目前为止我没有遇到任何问题),我认为它只包含了相关内容:
try {
SQLiteDatabase db = openDb();
ContentValues cv = new ContentValues();
cv.put("id", id);
cv.put("dateTime", dateTime);
long affected = db.replace("table", null, cv);
return affected;
} finally {
closeDb();
}
正如你所看到的,这里没有涉及火箭科学。但是,这个方法现在开始抛出类似的异常,发生在这一行:
long affected = db.replace("table", null, cv);
我开始怀疑它是一个点击太快的问题,并且SQLite连接没有足够的时间来关闭。因为我无法辨别崩溃的模式;有时它会在第三次尝试时崩溃,有时候会在第八次尝试时崩溃,有时它甚至可能会很好地工作直到第十次。
这可能吗?
答案 0 :(得分:1)
正如docs在你调用close()
之后说的那样,你的光标永远无效。
此外,您无需在功能中关闭2次。仅在finally
块中调用它就足够了
答案 1 :(得分:0)
因为你在静态对象上调用close()方法,所以它可能不一定“使”静态对象“无效”。因此,当您第二次检查openDb()方法中mDbHelper是否为null时,它将通过此条件,因此该方法将无意中返回已关闭的数据库。当您尝试查询此已关闭的数据库时,它将抛出非法状态异常。
尝试:
public SQLiteDatabase closeDb() {
mDbHelper.close()
mDbHelper = null;
}
我希望我有所帮助。