【问题标题】:Custom ContentProvider for complex sql database with multiple tables具有多个表的复杂 sql 数据库的自定义 ContentProvider
【发布时间】:2012-04-30 21:06:22
【问题描述】:

我正在尝试创建一个包含已编写应用程序中的功能的库。旧应用程序使用复杂的 sqlite 数据库。我正在尝试重用旧数据库作为内容提供者的后端,但无法弄清楚我正在尝试做什么以及如何调整各种示例的“最佳实践”(thisthis , 和其他人) 我发现了我的情况。

假设你有这个数据库结构

+------+-------------+-------------+-------------+
| Root |   Folder    |    Item     |  Subitem   |
+------+-------------+-------------+-------------+
| _id  | _id         | _id         | _id         |
| uuid | parent_uuid | parent_uuid | parent_uuid |
|      | uuid        | uuid        | uuid        |
|      | name        | name        | name        |
|      | data        | data        | data        |
+------+-------------+-------------+-------------+
Root->Folder->Item->Subitem

之前,我使用了一个 DbAdapter 类,在该类中我提供了函数调用,该函数调用采用 parent_uuid 等参数,处理函数内部的所有 sql 查询内容,然后返回带有结果的游标

示例函数存根:

  • get_items_by_parent_uuid(folder_uuid)
  • get_item_by_uuid(uuid)
  • Subitem 也一样

复杂查询

  • get_items_for_root(root_uuid)
    • 返回带有项目 uuid、项目名称、项目数据、文件夹名称的光标
  • get_items_with_subitem_count(folder_uuid)
    • 返回带有项目 uuid、项目名称、项目数据、子项目计数的光标,其中 subitem.parent_uuid == item.uuid

我想不出用 1 ContentProvider 提供上述功能的最佳方式。 我不需要有人给我写大量代码(但如果你这样做我也可以),我只是希望有人帮助我了解如何修改上面链接的示例来做这些事情,因为我主要做理解这些示例,但不足以将它们转化为我当前的需求。

TL;DR; - 如何编写单个 ContentProvider 来处理多个表,不依赖 _id 作为唯一标识符,并处理可能具有内部选择的连接-选择/查询(如select count(*)

【问题讨论】:

    标签: android android-contentprovider


    【解决方案1】:

    如何编写一个处理多个表的 ContentProvider

    第 1 步:为您的架构设计一个 REST 接口,将您自己限制为一个简单的 JSON 对象作为数据结构(即,没有嵌套的数组或对象,只是一个键到简单值的映射)

    第 2 步:将该设计转换为 ContentProvider,将 http://sooperapp.jp36.com/ 替换为 content://com.jp36.sooperapp,并将 JSON 替换为 CursorsContentValues

    因此,例如,您可能支持 content://com.jp36.sooperapp/foldercontent://com.jp36.sooperapp/itemcontent://com.jp36.sooperapp/subitem 作为检索/修改有关其中一种或多种类型的信息的基础。

    不依赖 _id 作为唯一标识符

    如果您打算使用CursorAdapter,并假设uuid 确实是指UUID(通常是一个字符串),那么您别无选择,只能使用_id。但是,如果您不打算使用CursorAdapter,则没有特别需要_id

    并处理连接以及可能具有内部选择/查询的选择(例如选择计数(*))

    这完全取决于您的 REST 接口/ContentProvider 设计。如果你想让content://com.jp36.sooperapp/folder/count 成为你所质疑的东西,那么在幕后,SELECT COUNT(*) FROM Folder 会不会让你失望。

    (注意:不要真的把自己弄晕了)

    如果您希望 content://com.jp36.sooperapp/omg/omg/omg/this/is/a/long/pathINSERTItem 和 17 Subitems 基于对提供商的一些 insert() 调用,请继续。 ContentProvider 只是一个门面;由您来定义Uri 的含义、ContentValues 的含义、query() 参数的含义等。

    就个人而言,我建议您退后一步,问问自己为什么要打扰ContentProvider

    【讨论】:

    • 好的,有很多问题。 ----- 1.当我创建ContentProvider时,我是否为每个表都有一个类,每个类将CONTENT_URI定义为content://com.jp36.sooperapp/{tablename}/*,然后在各个表类中具有单独的content_uri,例如@987654350 @ 类似于在这些对象中定义的content://com.jp36.sooperapp/{tablename}/fromparent/*? ----- 2. 如果我对content://com.jp36.sooperapp/folder/count进行查询,我将如何处理与我的预构建sql语句一起传入的String[] projection参数?
    • 基本上,我很确定我可以找到一些方法来使用ContentProvider 来做我所追求的,我的问题来自于试图找出 right/最佳实践 方法,以便下一个使用此库的人能够像使用 ContentProviders 提供的其他 Android 一样使用它。 ------- 另外,我想使用ContentProvider,因为它与 CursorLoaders 的集成很好,并且将来可能会使用 SyncAdapter。 -------- 非常感谢您迄今为止的帮助
    • @jp36:“我是否为每个表设置了一个类”——好吧,如果你愿意,你可以使用ContentProvider 委托逻辑来分隔类,这取决于你。但是,您将只有一个ContentProvider,因为它们与“权威”相关联(在我的示例中为com.jp36.sooperapp)。基本上,权限右侧的所有内容都由您来解释,除了指向特定记录的 Uri 值的实例 ID(它是最右边的整数段)。
    • @jp36:“我将如何处理 String[] 投影参数”——如果你愿意,你可以忽略它。同样,ContentProvider 是一个门面。除了Uri,您还可以定义query() 的参数的含义。
    • @firstcomment 假设使用单独的类类似于 Android 的做法,每个类将 CONTENT_URI 定义为 content://com.jp36.sooperapp/{tablename}/*,然后在单独的表类中具有单独的 content_uri,例如 @ 987654366@(类似于content://com.jp36.sooperapp/{tablename}/fromparent/*)是这样做的方法吗?
    猜你喜欢
    • 2012-04-10
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 2012-07-18
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    相关资源
    最近更新 更多