本节书摘来自异步社区《android开发进阶:从小工到专家》一书中的第1章,第1.4节contentprovider(外共享数据),作者 何红辉,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.4 contentprovider(外共享数据)
contentprovider在android中的作用是对外共享数据,也就是说可以通过contentprovider把应用中的数据共享给其他应用访问,其他应用可以通过contentprovider对应用中的数据进行添、删、改、查。使用contentprovider对外共享数据的好处是,统一了数据的访问方式,它实际上是对sqliteopenhelper的进一步封装,通过uri映射来判断选择需要操作数据库中的哪个表,并且进行增、删、改、查处理。
首先我们先来学习uri,uri代表了要操作的数据表的绝对路径,uri主要包含了两部分信息,一是需要操作的contentprovider,二是对contentprovider中的哪个表进行操作。对于contentprovider来说,一个uri由以下几部分组成,如图1-18所示。

contentprovider的scheme已经由android固定设置为content://,authority用于唯一标识这个contentprovider,外部调用者可以根据这个标识来找到它。这里的path就是要操作的数据库表,最后的id关键字是可选字段,例如,我们要操作特定的数据项时就会指定一个查询条件,如所有联系人的uri:content://contacts/people,某个联系人的uri: content://contacts/people/5,这个5就是联系人的id,也就对应了这里的查询关键字。
如果要把一个字符串转换成uri,可以使用uri类中的parse()函数,如下:
uri uri = uri.parse("content://contacts /people");
android系统根据uri来定位注册到系统的contentprovider中,找到contentprovider之后会通过contentresolver来操作对应的数据库。实现contentprovider的第一步就是需要覆写contentprovider的insert、query、upate、delete、gettype函数。下面我们要创建一个contentprovider,该contentprovider存储了一些服务行业人员的电话信息,如一些系统中就存储了快递人员、肯德基订餐电话等信息。我们要做的就是实现类似的功能,首先定义一个contentprovider,代码如下:
我们需要在contentprovider中根据uri建立关系映射,通过urimatcher管理不同uri对应的type类型,这个类型会在gettype中被返回。当在contentprovider中进行增、删、改、查操作时,就会根据这个类型选择对应的数据表。在这个例子中,我们通过urimatcher映射了4种uri类型, uri 的格式主要有两种,以表名结尾就表示期望访问该表中所有的数据,以id结尾就表示期望访问该表中拥有相应 id 的数据。我们可以使用通配符的方式来分别匹配这两种格式的内容uri,“*”表示匹配任意长度的任意字符,“#”表示匹配任意长度的数字。因此,content://com.book.jtm.info /userinfo表示要查询userinfo表中的所有数据,而content://com.book.jtm.info /userinfo/#表示要根据一个数字id查询一个用户。
下面我们就完成数据库操作的相关代码:
// 删除、更新的代码省略
上述代码中,我们把传递进来的uri通过urimatcher进行解析,得到type之后,再根据type来判断要操作哪个表,根据它的数据类型是所有数据还是单个数据,然后执行对应的数据库操作。对数据库的操作通过userinfodbhelper类实现。代码如下:
在userinfodbhelper中我们建立了两个表,分别为userinfo和company,表结构表1-2和表1-3所示。
完成contentprovider代码之后,第二步需要在androidmanifest.xml中使用对该contentprovider进行配置,为了能让其他应用找到该contentprovider ,contentprovider采用了authorities对它进行唯一标识,示例如下:
此时,我们就可以使用该contentprovider了。
我们新建一个provideractivity,在该activity中存储、查询用户信息,代码如下所示:
上述activity中我们可以将用户信息和公司信息根据不同的uri插入到同一个contentprovider中,userinfoprovider会根据uri选择对应的表进行插入,查询也是同样的道理。首先我们插入一条用户数据,该用户的电话为123456,描述为顺风快递员吴老二,公司id为11,插入之后我们可通过电话号码123456到contentprovider中查询该用户的信息,此时就会得到该用户的描述信息,如图1-19所示。
然后我们再插入该公司的信息,此时该conentprovider的数据库中就有了数据,我们将数据库导出到pc中,结果如图1-20和图1-21所示。
正如本章前文所说,contentprovider不过是对sqliteopenhelper的二次封装,通过urimatcher将数据库中的表与uri建立关联,当用户通过uri操作contentprovider时,contentprovider会根据uri选择对应的数据库表进行增、删、改、查操作。通过contentprovider机制,使得数据可以在各应用之间共享,并且为用户提供了统一的api接口,降低了用户的使用成本。