【问题标题】:SQLite When should I close the db and cursor? Should I use asynchronous invocation?SQLite 我应该什么时候关闭数据库和游标?我应该使用异步调用吗?
【发布时间】:2015-07-20 18:50:47
【问题描述】:

这个问题是这个问题的后续问题:

When should I close a cursor and db?

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

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

当他们关闭数据库或游标时,我看不到任何一致性。例如有一个关闭数据库的方法:

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(),但本教程中的方法是连续使用它的。哪种做法更好?

【问题讨论】:

  • 第一个 androidhive 是一个糟糕的教程源。关于关闭 SQLiteDatabase:通常,如果您不使用不同的进程,则根本不应该担心关闭 db ... 关于关闭游标:您应该在使用后关闭它(唯一的问题是当您使用 CursorAdapter 时,那么您应该使用旧的 manageQuery(已弃用但仍然)或更好:使用新的 Loaders Api - 这两种方法都将负责关闭游标)...
  • 你能不能稍微扩展一下,把它写成答案而不是评论?
  • 因为您也在询问 Cursor,所以它不是重复的,但这里是关于关闭数据库的类似问题:stackoverflow.com/questions/6608498/…

标签: android android-sqlite android-cursor


【解决方案1】:

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

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

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

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

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

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

延伸阅读:What is a “Memory leak” in Java?

来自 StackOverflow:Closing database connection to avoid memory leak

【讨论】:

  • 所以你是说我可以只在 onCreate 上打开一次数据库,然后在整个应用程序的生命周期中保持打开状态,直到 onDestroy 关闭,然后才关闭它?
  • 如果您在整个应用程序中广泛使用数据库连接,那么可以。那应该是使用的方法。因为创建数据库连接的成本非常高。并且不应该重复。但是如果你在应用程序中只需要它几次,那么你可以在方法本身中关闭连接。
  • 最佳实践是使用 ContentProvider 而根本不关闭数据库...应该只有 1 个连接...如果您不想遵循最佳实践,您可以使用只会保留的单例1个到数据库的连接......但你仍然无法有适当的事件来关闭它(因为可能不会调用onDestroy)
  • 添加 2 个数据库变量作为类成员是否合乎逻辑,一个用于可写,一个用于可读并打开它们?因为由于某种原因存在可写和可读的数据库。
  • 我认为这不合逻辑。因为,可写数据库也可以读取,因此,您可以使用它来读取和写入。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-23
  • 2021-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多