Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/205.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 安卓投影地图在内容提供商中的用途是什么?_Android_Android Contentprovider_Android Sqlite - Fatal编程技术网

Android 安卓投影地图在内容提供商中的用途是什么?

Android 安卓投影地图在内容提供商中的用途是什么?,android,android-contentprovider,android-sqlite,Android,Android Contentprovider,Android Sqlite,我正在查看/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. sNo

我正在查看
/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)

为什么需要这个投影图?

来自
SDK
demos的
Notepad
应用程序是一个示例应用程序,它应该是API使用和使用这些API的良好实践的一个示例,这就是为什么他们可能使用投影图。尽管
Notepad
示例并不真正需要投影图,但在需要投影图时,使用投影图可以很好地展示更复杂的情况。例如,如果我没记错的话,由一位谷歌工程师编写的
shelfs
应用程序在其
内容提供者中使用了一个投影映射,而该投影映射不仅仅是一个具有相同键值对的简单映射


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

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

@静态声明

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

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

此外,正如Juan所说,投影映射的目的是在进行连接时重命名列名并消除列名的歧义,投影映射的重要目的是针对恶意参数验证选择

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

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

  • 设置
    SQLiteQueryBuilder\setStrict(true)
  • 使用投影图
  • 使用其中一个查询重载,而不是将语句作为 sql字符串

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

  • 如果你不需要投影贴图,就不要设置它。这样,投影名称按“原样”处理,与通过投影数组传入的完全相同

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

  • 提供的投影贴图仅适用于选择列表!因此,您可以映射“store\u name”=>“bookstore.storename”,这将导致“select bookstore.storename…”,但如果您在“order by”查询生成器参数或其他限定参数中提供了“store\u name”,则可能会导致错误的SQL

  • 投影图可能被否决。如果投影条目的键部分包含“as”子句,则忽略值部分,并将键部分插入结果SQL。例如,“parrot as polly”=>“cracker”将生成“SELECT parrot as polly…”和“no cracker”。“as”可以是全大写或全小写(非混合大写),并且在“as”之前和之后必须至少有一个空格

  • 阅读本文中的更多信息:
    SQLiteQueryBuilder.setProjectionMap()的文档有很好的解释。谢谢。也许我的问题还不够清楚-我了解投影映射是什么,但我想知道,投影映射只包含具有相同键和值的映射有什么意义(如果至少有一个映射具有不同的键和值对,我会理解)。这是一个示例应用程序,一个应该是
    API
    使用的例子,以及使用那些
    API
    的良好实践,这就是他们可能使用投影地图的方式。比如说,如果我没记错的话,谷歌的一位工程师开发的
    shelfs
    应用程序在其
    ContentProvider
    中使用了一个投影图,而且投影图不仅仅是一个具有相同键值对的简单映射。谢谢-如果你把你的评论变成一个答案,我会接受。你能解释一下为什么使用投影吗地图?我不知道在查询和列名之间使用另一个名称有什么意义?@Paul当您使用
    SQLiteQueryBuilder
    进行比非常简单的查询更高级的场景时,需要使用投影图。例如,您可能希望在sqlite表的当前列名和您希望在应用程序中使用的一些任意名称之间建立别名(请检查
    AS
    sqlite关键字)。此外,在联接查询中,如果表中的列具有相同的名称,则可能需要不同的名称(最常见的情况是,两个表各自具有
    \u id
    列)。@azizbekian,谢谢您的夸奖。我在工作中发现了这一点,并寻找其他任何不理解这一点的人,就像这件事发生在我身上一样。
    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 );