13

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

我想知道是否有人可以向我解释为什么需要以下代码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

4 回答 4

10

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

我还添加了指向该方法文档的链接,SQLiteQueryBuilder.setProjectionMap其中包含有关为什么需要投影图的一些详细信息。

于 2012-10-09T12:27:36.503 回答
9

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

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

于 2015-07-03T01:21:15.590 回答
0

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

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

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

  1. SQLiteQueryBuilder#setStrict(true)
  2. 使用投影图。
  3. 使用查询重载之一,而不是将语句作为 sql 字符串获取
于 2016-03-25T15:18:21.343 回答
0

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

  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/

于 2016-08-19T14:05:01.580 回答