专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

Android开发ContentProvider应用程序的使

  概述
  ContentProvider以数据表的形式向外部应用程序提供数据,这与关系型数据库中的表很类似。其中,行(row)表示由多个不同类型数据构成的单个实体,每行数据中的列(column)代表实体中的一个数据项。
  例如,用户词典就是Android系统内置的Provider之一,里面记录着用户需要留存的自定义拼写规则的单词。表1例举了此Provider数据表中可以查询的字段信息:
  表1:用户词典表举例
  word
  appid
  frequency
  locale
  ID
  mapreduce
  user1
  100hrenUS
  1hrprecompiler
  user14
  200hrfrFR
  2hrapplet
  user2
  225hrfrCA
  3hrconst
  user1
  255hrptBR
  4hrint
  user5
  100hrenUK
  5hr在表1中,每行代表一个可能无法在标准词典中查到的单词。每列代表与单词相关的数据,比如首次使用时的地区(语言)。每列的标题即为存储时的列名称。引用locale列就可以得到每一行数据的地区信息。这里的ID列被用作主键(primarykey),并且是由Provider自动维护的。
  注意:Provider本身不需要用到主键,主键的名称也不一定要是ID。但是,如果要把Provider作为数据源与ListView绑定,则必须有一个列的名称是ID。详细要求将在显示查询结果中描述。访问Provider
  应用程序是通过客户端对象ContentResolver访问ContentProvider的。此对象中包含一些方法,这些方法将会调用Provider对象中的同名方法。而Provider对象是ContentProvider某个具体子类的实例。ContentResolver中的方法内置了基本的CRUD(创建、查询、更新、删除(create、retrieve、update和delete))功能。
  ContentResolver对象运行于客户端应用的进程中,而ContentProvider运行于提供Provider应用的进程中,两者会自动完成进程间的通讯。ContentProvider还发挥着数据抽象层的作用,负责将内部数据以数据库表的形式提供出来。
  注意:为了访问Provider,应用程序通常必须在Manifest文件中请求相应的权限
  例如,要从UserDictionaryProvider中读取单词及地区列表,就要用到ContentResolver。query()。query()方法会去调用UserDictionaryProvider中对应的ContentResolver。query()方法。以下代码演示了ContentResolver。query()的调用过程:1查询用户词典并返回结果2mCursorgetContentResolver()。query(3UserDictionary。Words。CONTENTURI,单词表的ContentURI4mProjection,需要返回的列5mSelectionClause,查询条件6mSelectionArgs,查询条件的参数7mSortOrder);返回结果的排序要求
  表2给出了query(Uri,projection,selection,selectionArgs,sortOrder)的参数与SQLSELECT语句的对应关系:
  表2:Query()与SQL查询的对比
  query()参数
  SELECT关键字参数
  说明
  Uri
  FROMtablename
  Uri对应于tablename指定的Provider数据表名。
  projection
  col,col,col,。。。
  projection是包含返回列名称的数组。
  selection
  WHEREcolvalue
  selection指定查询条件。
  selectionArgs
  (没有固定值,该查询参数将会替换查询语句中的占位符?。)
  sortOrder
  ORDERBYcol,col,。。。
  sortOrder指定了返回Cursor中各行的显示顺序。ContentURI
  ContentURI是一种用于标识Provider数据的URI。ContentURI包括了整个Provider的符号名称(authority)和表名(path)。调用客户端的方法访问Provider数据表时,表的ContentURI是参数之一。
  在前面的代码中,常量CONTENTURI包含了指向用户词典中word表的ContentURI。ContentResolver对象将分离出URI中的authority,并用它解析出Provider,这是通过将authority与系统记录的已有Provider清单进行比较来实现的。然后ContentResolver就可以将查询参数发送给相应的Provider了。
  ContentProvider用ContentURI的path部分选择要访问的数据表。通常,Provider公开的所有数据表都会带有自己的path。
  在上述代码中,word表的完整URI为:content:userdictionarywords
  这里的字符串userdictionary是Provider的authority部分,字符串words是数据表的path部分。字符串content:(scheme)是必须指定的,以表明这是一个ContentURI。
  很多Provider提供了对单条记录的访问能力,只要在URI后面跟一个ID值即可。例如,要读取用户词典中ID为4的数据行,可以使用以下ContentURI:UrisingleUriContentUris。withAppendedId(UserDictionary。Words。CONTENTURI,4);
  如果已经读取了一些数据,然后需要修改或删除其中的某一条,这时就经常会用到ID值了。
  注意:Uri和Uri。Builder类中已内置了一些工具性的方法,可以由字符串搭建合乎规则的Uri对象。ContentUris中有一些在URI后面追加ID值的常用方法。上述代码就用了withAppendedId()把ID追加到UserDictionary的ContentURI之后。从Provider读取数据
  本节将介绍从Provider读取数据的过程,还是以UserDictionaryProvider为例。
  为了清晰起见,本节中的代码将会调用UI线程中的ContentResolver。query()。但是在实际的代码中,应该在单独的线程中实现异步查询。一种方案是利用CursorLoader类,而且,以下只给出了部分代码,而非一个完整的应用程序。
  从Provider中读取数据的基本步骤如下所示:申请读取Provider的权限。编写向Provider发送查询请求的代码。申请读取权限
  要从Provider读取数据,应用程序需要拥有对Provider的读权限。在运行时是无法申请该权限的,只能在Manifest文件中通过指定。在Manifest文件中的定义,实际上是表明此应用程序需要申请该权限。这样用户在安装此应用程序时,就可以明确授权。
  在Provider的参考文档中,给出了其用到的全部权限的准确名称。
  UserDictionaryProvider在其Manifest文件中定义了android。permission。READUSERDICTIONARY权限,因此要读它的应用程序就必须请求该权限。构建查询
  接下来是构建查询请求。以下代码定义了一些变量,在访问UserDictionaryProvider时将会用到:1projection定义了要返回的数据列2String〔〕mProjection3{4UserDictionary。Words。ID,n对应列名为ID的ContractClass常量5UserDictionary。anclasstypWords。WORD,对应列名为word的ContractClass常量6UserDictionary。anclasstypWords。LOCALEnbLOCALE对应列名为local的ContractClass常量7};89定义存放查询条件的字符串10StringmSelectionClauseanclassplnnull;s;1112初始化存放查询参数的数组13String〔〕anclassplnmSelectionArgs{};
  接下来的代码演示了ContentResolver。query()的使用方法,这里以UserDictionaryProvider为例。Provider客户端查询与SQL查询很类似,也包含了需返回的列名、查询条件和排序要求。
  查询返回的列名集合对象被称为投影(Projection)(即变量mProjection)。
  查询数据的表达式被拆分为查询条件和查询参数。查询条件是由逻辑布尔表达式、列名、数值组成(即变量mSelectionClause)。如果用参数?代替了具体数值,则查询方法将会从查询参数数组(变量mSelectionArgs)中读取实际的值。
  在以下代码中,如果用户没有输入单词,则查询语句将被置为null,这样查询将会返回Provider中的所有单词。如果用户输入了单词,那么查询语句将会是UserDictionary。Words。WORD?,且查询参数数组中的第一个成员被设为用户输入的单词。12定义只有一个成员的字符串数组,用于存放查询参数。34String〔〕mSelectionArgs{};56从用户界面读取一个单词7mSearchStringmSearchWord。getText()。toString();89别忘了在这里添加检查输入内容是否非法或恶意的代码1011如果单词为空字符串,则读取所有数据12if(TextUtils。isEmpty(mSearchString)){13将查询语句设为null将返回所有数据14mSelectionClausenull;15mSelectionArgs〔0〕;1617}else{18由用户录入单词构建查询语句19mSelectionClauseUserDictionary。Words。WORD?;2021将用户录入的字符串置入查询参数数组中22mSelectionArgs〔0〕mSearchString;2324}2526查询数据并返回游标(Cursor)对象27mCursorgetContentResolver()。query(28UserDictionary。Words。CONTENTURI,单词表的ContentURI29mProjection,需返回的列30mSelectionClause为null或是用户录入的单词31mSelectionArgs,为空或是用户录入的字符串32mSortOrder);定义返回数据的排序规则3334在出错时,某些Provider返回null,另一些会抛出异常35if(nullmCursor){3637在这里插入处理错误的代码。38请勿在这里使用游标!39可能需要调用4041如果游标中没有内容,表示Provider没找到匹配的记录。42}elseif(mCursor。getCount()1){434445在这里插入通知用户查询失败的代码。46这不一定是出错了,可以让用户录入新记录,也可以重新输入查询条件。474849}else{50在这里插入处理查询结果的代码。5152}
  查询的语句与以下SQL语句类似:SELECTID,word,localeFROMwordsWHEREworduserinputORDERBYwordASC;
  这条SQL语句中使用的是真实的列名,而不是Contract类常量。防止非法输入
  如果ContentProvider管理的数据存放于SQL数据库中,那么在SQL语句中插入某些非法信息可能会引发SQL注入问题。
  请看下面这条查询语句:将用户输入内容拼接在列名之后,构造一条查询语句。StringmSelectionClausevarmUserInput;
  这时,用户就可以将恶意SQL拼接到查询语句中。比如,用户可以将mUserInput输入为nothing;DROPTABLE;,这样查询语句就会成为varnothing;DROPTABLE;。因为查询语句将用作SQL语句,所以会导致Provider删除底层SQLite数据库中的所有数据表(除非Provider设置为捕获SQL注入异常)。
  为了避免这类问题,可以在查询语句中使用?作为可替代参数,并用另一个数组作为实际的参数值。这样,用户的输入就与查询直接关联,而不会被解释为SQL语句的一部分。因为不再用作SQL语句,用户输入就无法注入恶意SQL了。用户的输入内容不直接用于拼接SQL语句,查询语句如下:用可替代参数构造查询语句StringmSelectionClausevar?;
  查询参数数组定义如下:定义存放查询参数值的数组String〔〕selectionArgs{};
  在数组中放入一个查询参数值:将查询参数赋为用户的输入值selectionArgs〔0〕mUserInput;
  在构造查询时,推荐使用这种将?作为形参、数组提供实参的查询语句,即使不是基于SQL数据库的Provider也可以使用。显示查询结果
  客户端方法ContentResolver。query()将返回一个Cursor,其中的数据列由对应查询条件的Projection指定。Cursor对象支持对数据行和数据列的随机读取。通过Cursor的内部方法,可以遍历结果数据行、获取每一列的数据类型、读取某一字段的数据并检查其他属性。某些Cursor对象可以在Provider的数据发生变化时进行自动更新,或是在Cursor数据变动时触发其他监听对象的方法。
  注意:根据建立查询的对象性质,Provider可以限制对数据列的访问。比如,联系人Provider就不允许SyncAdapter访问某些数据列,也就不会在Activity和服务中返回这些列。
  如果没有找到符合条件的数据,Provider就会返回一个Cursor。getCount()为0的Cursor对象(即空游标)。
  如果发生了内部错误,查询返回的结果将视Provider的不同而定。可能是返回null,也可能抛出一个Exception。
  因为Cursor是一个数据行的列表,所以一种较好的显示方式就是通过SimpleCursorAdapter把它与ListView关联起来。
  以下代码将延续上面的代码。创建了一个含有Cursor的SimpleCursorAdapter对象,并将其设置为一个ListView的数据源适配器(Adapter):1定义需要从Cursor读取并显示出来的数据列2String〔〕mWordListColumns3{4UserDictionary。Words。WORD,对应word列的Contract类常量5UserDictionary。Words。LOCALE对应locale列的Contract类常量6};78定义ViewID列表,用于保存Cursor返回的一行数据。9int〔〕mWordListItems{R。id。dictWord,R。id。locale};1011新建一个SimpleCursorAdapter对象12mCursorAdapternewSimpleCursorAdapter(13getApplicationContext(),应用程序的Context对象14R。layout。wordlistrow,XML格式的Layout,用于ListView中每一行的布局15mCursor,查询结果16mWordListColumns,字符串数组,存放游标中的列名17mWordListItems,整形数组,存放行布局中的ViewID180);标志位(一般用不上)1920设置ListView的Adapter21mWordList。setAdapter(mCursorAdapter);
  注意:要将Cursor用作ListView的后台数据源,游标必须包含一个名为ID的数据列。因此,上述查询从word表中读取了ID列,当然ListView并不会显示这个字段。这也是大部分Provider中的数据表都带有ID列的原因所在。从查询结果中读取数据
  查询结果不只是简单地用于显示,还可以用来完成其他操作。比如,可以从用户词典中读取单词并在其他Provider中进行检索。这时就需要遍历Cursor中的每行数据:1找到列名为word的字段编号2intindexmCursor。getColumnIndex(UserDictionary。Words。WORD);345仅当游标可用时才会执行。6如果发生内部错误,UserDictionaryProvider将会返回null。而其他Provider可能会抛出异常。789if(mCursor!null){1011前进至下一行。12在第一次移动之前,记录指针为1,如果这时读取数据,将会触发异常。1314while(mCursor。moveToNext()){1516读取值17newWordmCursor。getString(index);1819在这里插入处理返回单词的代码2021。。。2223while循环结束24}25}else{2627如果游标为空或Provider抛出异常,在这里插入显示错误的代码。28}
  Cursor中有很多用于读取不同类型数据的get方法。例如,上述代码中用到了getString()。还有一个getType()方法用于返回字段的类型。
  本文源代码获取方式:私信发送底层源码即可免费获取

猝不及防!她突然宣布退出三届大满贯冠军科贝尔宣布怀孕暂别赛场8月24日,三届大满贯得主科贝尔在社交平台上宣布怀孕喜讯。我很想参加美网,但最终觉得二打一不是那么公平。科贝尔表示。34岁的德国老将科贝尔已经夺中国男篮赢球仍有四大短板!周琦19分11板成遮羞布,杜锋仍需调整世预赛第四阶段比赛正式打响,中国男篮首战6856击败哈萨克斯坦男篮,顺利拿下比赛胜利。但从比赛的整个过程,球迷的表现和数据来看,中国男篮全队的表现难以让球迷非常失望,在经过一个多月41,43强势晋级第二轮北京时间8月26日消息,2022年WTT支线赛奥洛穆茨站继续坚持。女子单打第一轮一场焦点比赛,赛事3号种子张本美和爆冷一轮游,她以34输给意大利选手沙斯林。另一场比赛,中国小将吴洋郑智又收好消息!广州队有望签下30岁中国足坛神锋,保级希望大增北京时间8月25日,西班牙人俱乐部终于官方宣布了阿根廷球员巴尔加斯转会上海海港的消息。武巴连线这就来了。球员本人已经买了机票,预计下周抵达中国与球队汇合。近期,志在保级的广州队迎来111,中国乒乓球太强了,男乒3战3胜,女乒4将强势晋级北京时间8月26日消息,2022年WTT支线赛奥洛穆茨站,结束单打第一轮的争夺。中国队整体发挥非常出色,共有周启豪徐海东钱天一等7名选手获胜晋级。其中,三名男选手3战3胜,赛林威轰郑智再施妙手!补强恒大最大短板,李学鹏不堪大任或坐穿板凳郑智回归后,恒大可以说在各方面都有不同程度的提升,但上场对大连的比赛,恒大再次暴露最大短板左后卫。本赛季出任主力左后卫的小将陈日金,可以说不管能力还是经验都无法胜任主力位置,更何况半场惊魂!男篮本可以一波流带走比赛,为何却在下半场陷入苦战?面对失去核心归化外援克莱蒙斯的哈萨克斯坦,中国队此役赢得如此艰难出人意料。首先要感谢比赛只剩1分半钟时,朱俊龙追防穆尔扎加利耶夫时制造了对手移动掩护犯规,让球权得以转化,把哈萨克斯中国男篮新星耍大牌!拒绝签约广州队或被郭士强放弃在这个CBA休赛期,明星球员与老东家闹出矛盾比比皆是,包括郭艾伦甚至与辽宁男篮一度剑拔弩张。当然,除了郭艾伦,还有一些球员的去向没有确定,其中就包括了王泉泽,去年夏天他和广州龙狮签心灵港湾林紫目标与梦想之别梦想比目标更远一点点,无论眼前的目标有没有实现,都会一直充满激情朝着梦想而努力。晚餐时,我和女儿圆子一边享用美食,一边东拉西扯,不知怎么,突然就聊到了梦想。我说我觉得人还是要有些梦今日秋分我站在秋的路口,等一人归来午夜烟灰缸曰秋分,掬一捧秋色,与你平分。木叶落,秋分至,正是一年最美时。此时一片枫林,一黛远山,一江秋水,几痕江渚,数点白鹭沙鸥,秋便有了淡淡的远意。在这个意味阑珊的秋天,你是否发新赛季意甲冠军花落谁家?20222023赛季意甲联赛重燃战火,两轮战罢,有人欢喜有人愁。新赛季意甲冠军花落谁家犹未可知,但管中窥豹略见一斑,各家球队夏窗的引援质量在前两轮得到初步检验,主帅对球队的捏合调教
十二句高级文案,简短又吸引人一万丈高楼平地起,辉煌还得靠自己。二嘴巴是别人的,人生是自己的。三天真灿烂,尘世游慢,请拿出鼓动风云的勇敢。四敢在时间里自焚,必在永恒里结晶。五每一次困难,都是一次机会。六掌握坚持vivoX90系列正式发布,天玑9200骁龙8gen2,配置能把人吓坏vivoX90系列正式发布,最受关注的就是影像方面,依然堆料十足,作为X系列新十年开篇之作,vivoX90系列可以称得上是里程碑式的产品。众所周知,vivo手机一直以来都是以拍照为来自日本和歌山面料!BIGJOHN推出14。5oz重磅系列复古卫衣在2022年新货中,我们发现BIGJOHN推出一款PARKA风格的拉链卫衣,这是大约翰按照制造原色牛仔裤的高标准来打造出来的一件值得信赖的运动休闲卫衣。为了制作这样的产品,他们找到分享vivox80手机的几个细节趁着双11来临之际,在拼多多入手了2022年的真香机vivox80,之前看了很多评测以及用户分享,犹豫了很久,毕竟同时期价格,外观,照相素质发热能让我相中的不多。其中新平科技给予了世界杯情报卡塔尔主力中场缺阵,厄瓜多尔盼打破历史卡塔尔目前公布了球队的世界杯名单,效力加拉法的主力后卫霍马姆艾哈迈德(出场18次首发18次打进2球助攻1次)第一次入选。作为球队最近首发阵容里最年轻的球员,司职左翼卫,速度奇快,突世界杯历史上首批执法男足的女性裁判,汇聚卡塔尔在一个多世纪以来,国际足联都禁止女性裁判担任男子比赛的裁判,但在德甲英超和其他国家的国内竞赛都开始改变后,国际足联也开始改变了。我从来没想过这在2022年就会发生。作为本届世界杯六世界杯独立站球衣怎么赚(独立站足球球衣)跨境电商与世界杯在和平年代,足球就是男人的战争首轮战役已打响东道主很不高兴世界之巅四年一战你准备好了么?聚焦卡塔尔,有的人在等着夺冠有的人在观战有的人在赚钱你是哪一种呢?要赚钱不要等,Buynow为什么勤洗头,头皮屑还是多?别怪洗发水,是这4大因素引起的为什么勤洗头,头皮屑还是多?别怪洗发水,你需要注意这4大因素对于任何人来讲,头发是身体的一部分,它除了是正常的生理现象,还是很多人提升颜值的重要法宝,所以头发的好坏往往直接关系颜值长期冻疮患者亲测六款冻疮膏,到底哪一款才是性价比最高?每到入冬要选冻疮膏的时候都被琳琅满目的冻疮膏整的眼花缭乱,无从下手,看来看去还是买了综合排序第一。我选错的冻疮膏真的是数都数不清了。追求止疼止痒,结果灼伤皮肤盲目跟风买了不适合自己明星都爱的泰迪熊大衣,时髦保暖还高级,这个冬天赶紧穿起来秋日生活打卡季跟着明星学穿搭,才能让你走在时尚的前沿。明星的时尚嗅觉,都是非常敏感的。而且明星的同款单品,也会引来大众的模仿。冬天里明星都爱穿的泰迪熊大衣,不仅时髦保暖还特别高级显建议上了年纪的女人入冬少穿这4款外套,太油腻,换成呢大衣吧头条创作挑战赛爱美是很多人的天性,即使上了年纪也无法阻挡她们对于时尚的热爱。不过因为年龄增长,部分人可能会产生年龄焦虑,总想抓住时光的尾巴,选择一些不适合自己的单品扮酷耍帅,结果却
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网