Android: 我需要关闭Cursor对象吗?

8

在我的数据库适配器类中,我有很多像这样的方法:

public long getContactId(final String phoneNumber) throws SQLException {
    final Cursor cur = mDb.rawQuery(
            "select contact_id from contactphones where number=? limit 1;",
            new String[] { phoneNumber });
    return cur.moveToFirst() ? cur.getLong(0) : -1;
}

我很欣赏这种简洁的方法。但是我没有调用Cursor.close(),我不确定这是否有问题。在Cursor.finalize()中,Cursor会被关闭并释放其资源吗?否则我必须执行以下操作:

public long getContactId(final String phoneNumber) throws SQLException {
    final Cursor cur = mDb.rawQuery(
            "select contact_id from contactphones where number=? limit 1;",
            new String[] { phoneNumber });
    final boolean retVal = cur.moveToFirst() ? cur.getLong(0) : -1;
    cur.close();
    return retVal;
}
3个回答

2

是的,建议在使用完游标对象后关闭游标,以便游标可以在关闭时执行任何必要的清理工作。


1

Cursor不是一个类,而是一个接口。如果您的Cursor对象来自SQLite查询,则它是一个SQLiteCursor。在该定义中(\Android\android-sdk\source\android\database\sqlite\SQLiteCursor.java)close()finalize()函数中被调用。由于Cursor接口没有指定此行为,因此其他游标类型可能会有所不同。


20
这并没有回答这个问题。 - wvdz
close() 方法在 finalize() 方法中被调用,但这并不意味着我们不需要关闭游标!实际上,在完成游标操作后,我们必须关闭游标。为什么?因为我们不知道 finalize() 方法何时被调用,或者更糟糕的是,我们不知道它是否被调用。Java 不保证执行 finalize() 方法!还有其他原因,比如在 finalize() 方法中运行代码会导致性能问题和异常处理问题(finalize 方法中无法进行异常处理)。 - Alireza Ahmadi
那么为什么谷歌开发者将close()放在finalize()中呢?很简单:他们认为如果某些懒惰的开发者忘记调用close(),即使很晚并且不保证,他们也应该释放资源。这总比什么都没有好,对吧?总之,应该始终调用close()。您还可以在关闭后将光标设置为null。这样可以让垃圾收集器更快地将其从内存中删除,但我不建议这样做,因为它只是一个Java对象,通过这种方式获得的性能提升不会改变任何东西。 - Alireza Ahmadi

0

不要关闭数据库。没有必要(数据会在最早的机会安全地写入持久存储)。在应用程序启动时打开它一次,并在整个应用程序生命周期内重复使用同一个连接。

请参考此链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接