【问题标题】:When should I call close() on SQLiteOpenHelper used by ContentProvider我什么时候应该在 ContentProvider 使用的 SQLiteOpenHelper 上调用 close()
【发布时间】:2011-12-16 07:41:16
【问题描述】:

在我的 android 应用程序中,我使用 SQLiteOpenHelper 来实现 ContentProvider。 查询、添加、删除操作都是通过ContentProvider进行的。

但在我的一部 android 手机 (htc g13) 中,我在目录 /data/data/[package name]/databases 中找到了 *.db-wal 文件。并且使用 ContentProvider 操作时文件大小创建得非常快。它占用了太多的用户 RAM 空间。

建议关闭 SQLiteOpenHelper 以解决我在帖子enter link description here 中的问题(它很有用)。

但我想找一个“地方”来添加“close()”方法,因为我没有直接使用 SQLiteOpenHelper(通过 ContentProvider 使用)。 ContentProvider 中的 query() 方法必须返回一个 Cursor,并且 SQLiteDatabse 应该保持打开状态。

我很困惑,我现在做什么节目来保持 *.db-wal 消失并正常使用 ContentProvider?

【问题讨论】:

标签: android android-contentprovider sqliteopenhelper


【解决方案1】:

Android 框架工程师根据这个观点认为你需要关闭数据库。

根据 Dianne Hackborn(Android 框架工程师)in this thread

在创建托管进程时创建内容提供程序,并且 只要过程持续存在,所以没有必要 关闭数据库——它将作为内核的一部分关闭 当进程被杀死时清理进程的资源。

【讨论】:

    【解决方案2】:

    你有几个案例要介绍:

    1) 当您的应用程序完成时(例如输入 onDestroy()),请确保您关闭所有游标、SQLiteDatabase 和 SQLiteOpenHelpers 的数据库实例(使用模型 if (connection.isOpen()) object.close())

    2) 当您的应用程序继续 onPause() -> onResume() - 适当地使用此阶段来暂停/恢复您的连接或关闭/打开它们。

    使用完数据库后立即关闭数据库是一种很好的做法。数据库是缓存的,所以关闭它并在需要时使用 getWritableDatabase()/getReadableDatabase() 再次重新获取实例是没有问题的

    来自官方文档: “一旦打开成功,数据库就会被缓存,所以每次需要写入数据库时​​都可以调用这个方法。(当你不再需要数据库时,一定要调用close()。)”

    另外请记住,如果 SQLiteOpenHelper 缓存并跟踪所有打开的 SQLiteDatabase 实例,这基本上意味着如果您不保留打开的数据库连接,则不必在 SQLiteOpenHelper 上调用 close。

    我建议在停止使用所有游标和数据库后立即关闭它们。始终尝试强制执行 try/catch/ 查询操作和“finally 块”来调用对象的关闭方法。

    【讨论】:

    • 谢谢hovanessyan!但困扰我的是我的应用程序支持多线程,我不知道“什么时候”应用程序真的不需要数据库。第二个问题是:我面临的是 ContentProvider(也许 ContentResolver 会是准确的),从层设计的角度来看,我无法轻松获得 SQLiteDatabase 或 SQLiteOpenHelpers 的参考。我讨厌 ContenProvider 的概念!
    • 如果您为 DB 调用使用单独的线程,我假设您将使用 AsyncTasks。如果是这种情况,您在 doInBackground() 中执行所有操作并在 onPostExecute() 中关闭对象。我无法理解另一个问题。能否详细说明一下这一层的设计点>?
    • 我已经尝试过您建议的逻辑,但遇到了“数据库已关闭”之类的异常。我认为代码执行 seq 如下:1。线程 A getWritableDatabase(); 2.线程B关闭数据库; 3.线程A执行sql查询异常发生!
    • 为什么不使用一个线程来处理所有数据库操作? AsyncTasks 会自动为您处理线程。
    • 是的,我认为这种方法可以。但是如果我必须使用 ContentProvider/ContentResolver,而不是直接使用数据库引用呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 2010-09-16
    • 1970-01-01
    相关资源
    最近更新 更多