0

当您在游标对象上调用 .close() 时,是否意味着在 Activity 的其余时间段内不能使用它?以下是我的 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);

只是为了澄清一点,这个方法可以在 Activity 的生命周期内通过单击特定的 ListView 项目多次调用。openDb() 和 closeDb() 方法如下:

public SQLiteDatabase openDb() {
    if (mDbHelper == null) {
        mDbHelper = new DatabaseHelper(mContext);
    }
    return mDbHelper.getWritableDatabase();
}

public void closeDb() {
    mDbHelper.close();
}

这些存储在我的 Manager 对象的超类中。mDbHelper 是一个静态对象。

作为 Android 编程的新手,我想知道为什么这会给我一个异常。我能想到的唯一合乎逻辑的解释是光标对象实际上是重复使用的,它们不应该在活动期间关闭。我对吗?如果我是,你什么时候真正关闭光标?

- -编辑 - -

在稍微修改了代码之后,我似乎在更不规则的基础上抛出了异常。出于某种奇怪的原因,它似乎是随机发生的;我可以毫无问题地单击八个多个 ListView 项目,然后突然砰!第九个导致应用程序崩溃。

因为单击 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 连接没有足够的时间来关闭。因为我无法辨别崩溃的模式;有时它在第三次尝试时崩溃,有时在第八次尝试时崩溃,有时它甚至在第十次之后似乎都可以正常工作。

这可能吗?

4

2 回答 2

1

正如文档所说,在您调用close()光标后,您的光标将永远无效。

此外,无需在您的函数中调用 close 2 次。finally仅在块中调用它就足够了

于 2013-06-25T02:18:15.043 回答
0

因为您在静态对象上调用 close() 方法,它可能不一定“使”静态对象“无效”。所以当你第二次在 openDb() 方法中检查 mDbHelper 是否为 null 时,它会通过这个条件,因此该方法会无意中返回一个关闭的数据库。当你尝试查询这个关闭的数据库时,它会因此抛出非法状态异常。

尝试:

public SQLiteDatabase closeDb() {
    mDbHelper.close()
    mDbHelper = null;
}

我希望我有所帮助。

于 2013-06-25T02:13:36.337 回答