【问题标题】:Do I Need to Create/Use a Content Provider我需要创建/使用内容提供者吗
【发布时间】:2014-05-16 21:23:09
【问题描述】:

我一直在尝试解决有关我的应用程序和应用程序服务共享使用 SQLiteDatabase 的问题;即应用程序启动的服务。该服务每 30 秒唤醒一次并检查数据库,然后,就像所有好的进程一样,它在完成后关闭与数据库的连接。但是,当应用程序同时运行并尝试访问数据库时,应用程序会崩溃。 logcat 显示一条消息,警告我正在尝试重新打开已关闭的数据库连接,如下所示:

05-16 16:48:30.796: E/AndroidRuntime(10610): java.lang.IllegalStateException:尝试重新打开已经关闭的 对象:SQLiteDatabase:/data/data/com.example.myapp/databases/eRing

一项勤奋的故障排除工作表明,如果我取消了服务对数据库的关闭,一切都会好起来的,有点……如果我让服务周期足够长。最终,SQLiteConnectionPool 会醒来并说,

数据库的 SQLiteConnection 对象 '+data+data+com_example_myapp+databases+eRing' 被泄露了!请修复 您的申请以正确结束正在进行的交易并关闭 不再需要的数据库。

所以,我回到了绘图板上,查看了文档和教程。我注意到许多可用资源在不讨论 ContentProvider 的情况下几乎无法提及 SQLiteDatabases。但是,文档说,如果您打算从另一个应用程序访问数据库,则只需要 ContentProvider。以下是来自 Android 开发者网站的引述:

开始构建之前

在开始构建提供程序之前,请执行以下操作:

  1. 确定您是否需要内容提供商。如果要提供以下一项或多项,则需要构建内容提供程序 特点:

    • 您想向其他应用程序提供复杂的数据或文件。
    • 您希望允许用户将复杂数据从您的应用复制到其他应用中。
    • 您想使用搜索框架提供自定义搜索建议。

    如果使用完全在您自己的应用程序中,您不需要提供者来使用 SQLite 数据库。

我无法从这个文档中看出以下几点:对于 App 拥有 Service,并且 Activity 和 Service 都需要同时访问数据库的情况,这是否需要创建 ContentProvider?我很肯定我无意与其他任何东西或文档列出的任何其他场景共享此数据库。换句话说,Service 和 Activity 算不算两个“应用程序”? Android 基础知识将活动和服务称为“应用组件”,而不是单个“应用”。

请告诉我,是否值得付出所有努力来创建自定义 ContentProvider,并消除对数据库的直接访问(通过 SQLiteDBAdapters/Helpers)是否值得。

For Salem:下面是Activity和Service调用的close方法。

public class SettingsDbAdapter {

private static SQLiteDatabase mDb;
private DatabaseHelper mDbHelper;

public static class DatabaseHelper extends SQLiteOpenHelper {
   //...

    }

//...
public void close() {
        Log.v("close()", "Close settingsdbadapter called");
        mDbHelper.close();
    }

}

//The following is the Services Open method:

public SettingsDbAdapter openReadable() throws SQLException {
    mDbHelper = new DatabaseHelper(mCtx);
    mDb = mDbHelper.getReadableDatabase();

    return this;
}

//The following is the Activities Open Method:
public SettingsDbAdapter open() throws SQLException {
            mDb = mDbHelper.getWritableDatabase();
    if (!mDb.isWriteAheadLoggingEnabled()) {
        Log.v("SettingsDb","Trying to Enable Write Ahead Logging");
        mDb.enableWriteAheadLogging();
    }
    return this;
}

【问题讨论】:

  • 你能提供一个打开/关闭连接的代码的sn-p吗?
  • @Salem 请参阅上面的修订版。
  • 尝试用if (mDbHelper != null && mDbHelper.isOpen()) { mDbHelper.close(); }替换mDbHelper.close();
  • @Salem,我假设您的意思是 mDb.isOpen?它产生相同的结果。

标签: android sqlite


【解决方案1】:

只有当另一个应用程序访问数据库时才需要内容提供者,因为后者根本没有打开数据库文件的权限。

就您而言,问题在于您可以同时访问SQLiteDatabase。如果您编写了服务,您的活动也应该使用它。

编辑:我的评论看起来很混乱,我删除了它。我建议以下 4 个组件:

  • 一个BroadcastReceiver,在手机启动后,注册一个警报(通过AlarmManager),然后关闭
  • 另一个广播接收器,接收来自闹钟的滴答声(闹钟是 Android 实现的服务)并检查数据
  • 显示/允许编辑数据的活动

后两者通过

访问数据
  • 一种提供在数据库中读取/保存业务对象的方法的服务

【讨论】:

  • 你可能让我大吃一惊。你是在告诉我我需要重新架构它,以便服务将数据传递给活动?
  • 如果是这样,如果 Service 在启动时启动(例如这里://stackoverflow.com/questions/2784441/…),Activity 仍然可以到达 Service 吗?
  • 是的。该服务可以提供操作数据和管理底层 SQLiteDatabase 连接的服务。根据您的偏好和活动所需的数据量,您可以选择低级服务或IntentService
  • 是的:Mind=Blown。我会摆弄这些概念。
  • 我将尝试提出的解决方案,因为它确实与文档不符,但仍然想知道是否可以使用 ContentProvider 代替管理数据库的服务来实现有效的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 2022-11-14
  • 2022-07-09
  • 1970-01-01
相关资源
最近更新 更多