内容提供商中Android投影地图的目的是什么?

时间:2012-10-05 16:51:27

标签: android android-contentprovider android-sqlite

我正在查看<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;
...

为什么需要这个投影图?

4 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分:7)

其主要目的是重命名由查询生成的游标中的列名。

@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" );  

@your查询功能

//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。

答案 2 :(得分:0)

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

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

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

  1. 设置SQLiteQueryBuilder#setStrict(true)
  2. 使用投影地图。
  3. 使用其中一个查询重载,而不是将语句作为a sql string

答案 3 :(得分:0)

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

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

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

  3. 提供的投影图仅适用于选择列表!所以,你可以映射“store_name”=&gt; “bookstore.storename”,它会导致“select bookstore.storename ...”,但如果您在“order by”查询构建器参数或其他一个合格参数中提供了“store_name”,则可能最终错误的SQL。

  4. 可以推翻投影地图。如果投影条目的关键部分包含“as”子句,则忽略值部分,并将关键部分插入到生成的SQL中。例如“parrot as polly”=&gt; “cracker”将产生“SELECT polrot as polly ......”而不会产生“cracker”。 “as”既可以是大写也可以是全部小写(不是混合大小写),并且必须在单词“as”之前和之后至少有一个空格。

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