处理Cursor对象的正确方法

时间:2013-06-25 01:47:44

标签: android cursor

当你在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连接没有足够的时间来关闭。因为我无法辨别崩溃的模式;有时它会在第三次尝试时崩溃,有时候会在第八次尝试时崩溃,有时它甚至可能会很好地工作直到第十次。

这可能吗?

2 个答案:

答案 0 :(得分:1)

正如docs在你调用close()之后说的那样,你的光标永远无效。

此外,您无需在功能中关闭2次。仅在finally块中调用它就足够了

答案 1 :(得分:0)

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

尝试:

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

我希望我有所帮助。