SQLite 什么时候应该关闭数据库和游标?我应该使用异步调用吗?

SQLite When should I close the db and cursor? Should I use asynchronous invocation?

此问题是此问题的后续问题:

When should I close a cursor and db?

我正在学习如何将 SQLite 用于 Android,我正在使用本教程作为示例:

http://www.androidhive.info/2011/11/android-sqlite-database-tutorial/

当他们关闭数据库或游标时,我没有看到任何一致性。例如,有这种方法可以关闭 db:

public void addContact(Contact contact) 
{
SQLiteDatabase db = this.getWritableDatabase();

ContentValues values = new ContentValues();
values.put(KEY_NAME, contact.getName()); // Contact Name
values.put(KEY_PH_NO, contact.getPhoneNumber()); // Contact Phone Number

// Inserting Row
db.insert(TABLE_CONTACTS, null, values);
db.close(); // Closing database connection
}

但是在它之后有这个方法不会关闭它:

public Contact getContact(int id) {
SQLiteDatabase db = this.getReadableDatabase();

Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID,
        KEY_NAME, KEY_PH_NO }, KEY_ID + "=?",
        new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
    cursor.moveToFirst();

Contact contact = new Contact(Integer.parseInt(cursor.getString(0)),
        cursor.getString(1), cursor.getString(2));
// return contact
return contact;
}

关闭光标也是如此。

为什么在添加联系人后关闭数据库是正确的,但在获取联系人后却不正确?在调用 getWritableDatabase()getReadableDatabase() 之后总是关闭数据库是一个好习惯吗?另外,如果我想向数据库中添加多个项目,保持与数据库的连接打开并一个接一个地插入许多项目是一个好习惯,还是我应该以某种方式将它们全部插入到一个查询中?

我还读到你想用 AsyncTaskIntentService 调用 getWritableDatabase()getReadableDatabase(),但教程中的方法是连续使用它的。哪种做法更好?

是的,应该在使用后始终关闭数据库连接。

可写数据库连接更容易受到攻击,因为某些其他进程可能会访问未关闭的数据库连接并对数据库进行更改。他们无法通过未关闭的可读数据库连接来完成。

应尽量减少内存泄漏。 我昨天刚回答过类似的问题。在这里:

Java 中的内存泄漏是应用程序不再使用某些对象的情况,但垃圾收集无法将它们识别为未使用,因此不会将其清理。

每次创建对象时,都会为该对象保留一些 space 内存。任何数据库连接也是如此。所以,在使用连接之后,如果你不关闭它,GC 就不知道这个对象将不再被使用,因此不会删除它。因此,它保留在内存中,在程序的其余部分运行时消耗宝贵的资源。 [因此资源泄漏]。

这根本不是我们想要的。此外,这会使您的程序面临安全问题,因为连接是打开的,它很容易受到攻击,并且可以对数据库进行更改。请记住,即使在 Activity 关闭后,如果存在 运行 线程或 AsyncTask,数据库连接也会与线程一起保持打开状态。

进一步阅读:What is a “Memory leak” in Java?

来自 Whosebug:Closing database connection to avoid memory leak