Android 处理光标对象的正确方法

Android 处理光标对象的正确方法,android,cursor,Android,Cursor,在对游标对象调用.close()时,是否意味着在活动的剩余时间内不能使用它?以下是my Manager对象中的一个方法: Cursor cursor = null; try { SQLiteDatabase db = openDb(); cursor = db.query("table", null, "id=?", new String[] { id }, null, null, null); cursor.moveToFirst(); long dateT

在对游标对象调用.close()时,是否意味着在活动的剩余时间内不能使用它?以下是my 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();
}
这就是给我抛出非法状态异常的方法。然而,有一个小小的转变:它只在第二次调用时抛出一个错误。追踪stacktrace,我发现给我带来麻烦的线路如下:

Cursor cursor = db.query("table", null, "id=?", new String[] { id }, null, null, null);
只需稍微澄清一下,通过单击特定的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连接没有足够的时间关闭。因为我看不出崩溃的模式;有时它在第三次尝试时崩溃,有时在第八次尝试时崩溃,有时它甚至在第十次尝试后仍然可以正常工作

这可能吗?

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

尝试:

我希望我能帮上忙。

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


此外,在函数中不需要调用close两次。只需在
finally
块中调用它就足够了

我每次都使用db.query()创建一个新的游标。所以这应该不是问题,对吗?@Wakka02只要你记得在使用后关闭它,这没有问题。不过我确实关闭了它。我在所有finally语句中都包含了cursor.close()。感谢Alex指出这里的double.close(),我已经解决了这个问题。还是没用/我不这么认为。。。openDb()执行该检查以确保没有抛出空指针,它仍然使用.getWritableDatabase()返回有效的开放数据库。您能在编码中测试此实现吗?我只是测试了,它没有解决问题。。。这就是我在评论中提出这个理论的原因。哦,太好了。我会继续研究:)谢谢各位的回答和评论,但由于似乎没有一个随机性的答案,我开发了一个解决方法来捕获所有异常,并在它们发生时做一些事情。我相信有一个答案可以完全解决这个问题,而头脑只是一个暂时的方法,所以我将把这个问题留给大家先回答。
public SQLiteDatabase closeDb() {
    mDbHelper.close()
    mDbHelper = null;
}