【问题标题】:What is the purpose of an Android projection map in a content provider?内容提供者中的 Android 投影图的目的是什么?
【发布时间】:2012-10-05 16:51:26
【问题描述】:

我在看<path_to_SDK>/samples/android-16/NotePad/src/com/example/android/notepad中的Android记事本应用示例代码。

我想知道是否有人可以向我解释为什么NotepadProvider.java 中需要以下代码?

// Creates a new projection map instance. The map returns a column name
// given a string. The two are usually equal.
sNotesProjectionMap = new HashMap<String, String>();

// Maps the string "_ID" to the column name "_ID"
sNotesProjectionMap.put(NotePad.Notes._ID, NotePad.Notes._ID);

// Maps "title" to "title"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_TITLE,NotePad.Notes.COLUMN_NAME_TITLE);

// Maps "note" to "note"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_NOTE, NotePad.Notes.COLUMN_NAME_NOTE);

// Maps "created" to "created"
sNotesProjectionMap.put(NotePad.Notes.COLUMN_NAME_CREATE_DATE, NotePad.Notes.COLUMN_NAME_CREATE_DATE);

// Maps "modified" to "modified"
sNotesProjectionMap.put(
        NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE,
        NotePad.Notes.COLUMN_NAME_MODIFICATION_DATE)

我注意到投影图稍后在query() 方法中使用:

...
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
qb.setTables(NotePad.Notes.TABLE_NAME);

/**
 * Choose the projection and adjust the "where" clause based on URI pattern-matching.
 */
switch (sUriMatcher.match(uri)) {
    // If the incoming URI is for notes, chooses the Notes projection
    case NOTES:
    qb.setProjectionMap(sNotesProjectionMap);
    break;
...

为什么需要这个投影图?

【问题讨论】:

  • SQLiteQueryBuilder.setProjectionMap() 的文档有很好的解释。
  • 谢谢。也许我的问题不够清楚 - 我了解投影图是什么,但我想知道拥有一个仅包含具有相同键和值的映射的投影图有什么意义(如果至少有一个映射,我会理解有不同的键值对)。
  • 这是一个示例应用程序,应该是 API 使用的示例和使用 APIs 的良好实践,这就是他们可能使用投影图的方式。例如,如果我没记错的话,一位谷歌工程师制作的Shelves 应用程序在其ContentProvider 中使用了投影图,并且该投影图不仅仅是具有相同键值对的简单映射。跨度>
  • 谢谢 - 如果你把你的评论变成一个答案,那么我会接受它。

标签: android android-contentprovider android-sqlite


【解决方案1】:

SDK 演示中的Notepad 应用程序是一个示例应用程序,它应该是 API 使用示例和使用这些 API 的良好实践,这就是它们可能使用投影图的原因。尽管Notepad 示例并不真正需要投影图,但在需要投影图时,使用投影图可以很好地展示更复杂的情况。例如,如果我没记错的话,由 Google 工程师之一编写的 Shelves 应用程序在其 ContentProvider 中使用了投影图,并且该投影图不仅仅是具有相同键值对的简单映射。

我还添加了指向方法 SQLiteQueryBuilder.setProjectionMap 的文档的链接,其中详细说明了为什么需要投影图。

【讨论】:

  • 您能解释一下为什么要使用投影图吗?我不确定在查询和列名之间使用另一个名称的意义?
  • @Paul 当您将SQLiteQueryBuilder 用于比非常简单的查询更高级的场景时,需要该投影图。例如,也许你想在一个 sqlite 表的当前列名和你在你的应用程序中想要的一些任意名称之间创建一个别名(检查AS sqlite 关键字sqlite.org/syntaxdiagrams.html#result-column)。同样在连接查询中,如果您的表具有相同名称的列(最常见的是两个表,每个表都有一个 _id 列),您可能需要不同的名称。
【解决方案2】:

它的主要目的是重命名在查询产生的游标中找到的列名。

@static 声明

SEARCH_PROJECTION_MAP = new HashMap<String, String>();
SEARCH_PROJECTION_MAP.put( OpenHelper.NAME, OpenHelper.NAME + " as _name" );
SEARCH_PROJECTION_MAP.put( OpenHelper.ID , OpenHelper.ID + " as _id" );  

@您的查询功能

//if you query using sqliteQueryBuilder then
    sqLiteQueryBuilder.setProjectionMap( SEARCH_PROJECTION_MAP );

//example if you just query
    Cursor cursor = sqLiteQueryBuilder.query( db, projection, selection, selectionArgs, null, null, sortOrder );

在本例中,现在返回的列是 _name 和 _id。

【讨论】:

  • @azizbekian,感谢您的夸奖。我在工作时发现并寻找其他不理解的人,就像发生在我身上一样。
  • 这是我见过的唯一实际使用投影图的例子。你是绝对的明星。我很难让它工作,因为我的假设是它会在查询中作为“ AS ”工作,而不仅仅是用“”替换你的列名。
【解决方案3】:

除了如胡安所说,投影图的目的是在进行连接时重命名列名以及消除列名的歧义,投影图的重要目的是验证选择是否有恶意参数。

当使用SQLiteQueryBuilder 创建使用buildQueryString(boolean, String, String[], String, String, String, String, String) 的语句时,如果指定了投影图,则不在该图中的字段将被忽略。

要获得针对恶意第三方应用程序(例如内容提供者消费者)的最大保护,您可以执行以下操作:

  1. 设置SQLiteQueryBuilder#setStrict(true)
  2. 使用投影图。
  3. 使用查询重载之一,而不是将语句作为 sql字符串

【讨论】:

    【解决方案4】:

    也许有人需要更彻底的解释。我收集了有关投影图的重要事实:

    1. 如果您不需要投影图,请不要设置它。这样,投影名称将“按原样”处理,与通过投影数组传入的完全一样。

    2. 甚至投影阵列也是可选的。如果将 null 传递给查询,它会生成“SELECT *”操作。 (实际上在 SQL 中不建议这样做,因为如果添加/删除或重新排序列可能会发生损坏)。

    3. 提供的投影图仅适用于选择列表!因此,您可以映射“store_name”=>“bookstore.storename”,这将导致“select bookstore.storename ...”,但如果您在“order by”查询构建器参数或其中之一中提供“store_name”其他合格的参数,您可能最终会遇到错误的 SQL。

    4. 投影图可以被否决。如果投影条目的键部分包含“as”子句,则忽略值部分并将键部分插入到生成的 SQL 中。例如 "parrot as polly" => "cracker" 将生成 "SELECT parrot as polly ..." 而没有 "cracker"。 “as”可以全部为大写,也可以全部为小写(不能混合大小写),并且“as”前后必须至少有一个空格。

    在本文中阅读更多信息: http://www.mousetech.com/blog/android-projection-maps-explained/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-23
      • 1970-01-01
      • 2012-12-05
      • 1970-01-01
      相关资源
      最近更新 更多