1.什么是内容提供者?
首先在android 开发艺术探索这边书中 我们都知道ContentProvider(内容提供者)是android中的四大组件之一,但是在一般的开发中,可能使用比较少。ContentProvider为不同的软件之间数据共享,提供统一的接口。而且ContentProvider是以类似数据库中表的方式将数据暴露,也就是说ContentProvider就像一个“数据库”。那么外界获取其提供的数据,也就应该与从数据库中获取数据的操作基本一样,只不过是采用URI来表示外界需要访问的“数据库”。至于如何从URI中识别出外界需要的是哪个“数据库”这就是Android底层需要做的事情了,也就是说,如果我们想让其他的应用使用我们自己程序内的数据,就可以使用ContentProvider定义一个对外开放的接口,从而使得其他的应用可以使用我们自己应用中的文件、数据库内存储的信息。当然,自己开发的应用需要给其他应用共享信息的需求可能比较少见,但是在Android系统中,很多数据如:联系人信息、短信信息、图片库、音频库等,这些信息在开发中还是经常用到的,这些信息谷歌工程师已经帮我们封装好了,我们可以使用谷歌给我的Uri去直接访问这些数据。所以对于ContentProvider我们还是需要认真的学习的,在遇到获取联系人信息,图片库,音视频库等需求的时候,才能更好的实现功能。
2.为什么会有内容提供者?
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据。而使用ContentProvider共享数据的好处是统一了数据访问方式,这也是为什么会有内容提供者的原因。
在这里解释一下:怎么理解ContentProvider统一了数据访问方式
根据官网上的描述,content provider主要是提供应用程序之间的数据共享。比如App A 需要App B的数据能用shared preference?用文件的话,还只能用external file,但是可能没有外存,文件可能会被删除,权限问题等等。所以content provider+content resolver是最好的方式。
而且记住,content provider+content resolver只是提供了应用程序之间的一个通道,具体的数据处理是在content provider中,contetn provider 对底层的数据存储方法没有任何的要求 有可能是文件,可能是sqlite,也有可能是采用内存中的一个对象来进行数据存储。
3.应该怎么实现自己的ContentProvider?
下面是一个简单的实列 他演示了ContentProvider的工作过程 首先是创建一个MyContentProvider类 ,它继承ContentProvider并实现了ContentProvider的六个必须要实现的方法 在下面代码中 我们什么都么有干 尽管如此 这个MyContentProvider 也是可以工作的 只是它无法向外界提供有效的数据而已
![](https://i-blog.csdnimg.cn/blog_migrate/a42cc012ac6f4fbffddc3477edf95704.webp?x-image-process=image/format,png)
然后接着我们需要在功能清单中Manifest中注册 MyContentProvider 如下图所示 其中 android:authorities="star.liuwen.com.endcontentprovider.MyContentProvider" 是ContentProvider中的唯一标识 而process 则是独立进程的标志
![](https://i-blog.csdnimg.cn/blog_migrate/0bcbbbc5d1aa2dfaf141ca42bd06c335.webp?x-image-process=image/format,png)
![](https://i-blog.csdnimg.cn/blog_migrate/8f3955bcd20a03f96cda1fd4e5167b1b.webp?x-image-process=image/format,png)
然后我们可以看到打印出来的日志
![](https://i-blog.csdnimg.cn/blog_migrate/caed3d246ad2d736be5ce44bdb6274fa.webp?x-image-process=image/format,png)
从日志中我们可以看到MyContentProvider 中的query方法被调用了三次 并且三次都是在不同的线程当中 可以看出来 他们都是运行在一个BInder线程当中 而onCreate()方法则是在主线程当中 也就是我们的UI线程
到这里 我们自定义的MyContentProvider 已经跑通了 虽然MyContentProvider 中没有返回任何的数据 所以接下来 我们继续完善 需要MyContentProvider 能够对外提供数据 上面我写了Contetn provider 对底层的数据存储方法没有任何的要求 可以是文件 也可以是SqLite 这里我们简单的用SqLite来实现存储
![](https://i-blog.csdnimg.cn/blog_migrate/3e916a92a497b02d62982c831257b40f.webp?x-image-process=image/format,png)
上面代码是一个简单的数据库实现 我们借助SqLiteHelper 来管理数据可的创建 支持 和升级 下面我们就要通过MyContentProvider向外界提供数据库中的信息 我们知道 ContentProvider 是通过Uri 来区分外界要访问的数据集合 在本列中支持外界对MyContentProvider 中的book表 和user表进行访问 为了知道外界要访问的是哪个表 我们需要为他们定义单独的Uri 和Uri_code 并将Uri和Uri_code 相关联 我们可以使用UriMatcher的addUrI方法将Uri_code关联到一起 这样 当外界请求访问MyContentProvider 时,我们就可以根据请求的Uri来得到Uri_code 有了Uri_code 我们就可以知道外界想要访问哪个表 然后就可以进行相应的数据操作了
![](https://i-blog.csdnimg.cn/blog_migrate/4f4d62aa543e7991bf9133facfdefacd.webp?x-image-process=image/format,png)
![](https://i-blog.csdnimg.cn/blog_migrate/6b4c7c1ee66a87ff4e324c181a65f977.webp?x-image-process=image/format,png)
![](https://i-blog.csdnimg.cn/blog_migrate/d4fd796b616b6bb8e56e9a8a14da9cc0.webp?x-image-process=image/format,png)
![](https://i-blog.csdnimg.cn/blog_migrate/f518f6e5a7a89d8a257dfabb3651e7d9.webp?x-image-process=image/format,png)
完整代码就是这样的
下面在看Activity中的 代码
![](https://i-blog.csdnimg.cn/blog_migrate/4bde76edba8d43b6607f808fa0a09646.webp?x-image-process=image/format,png)
![](https://i-blog.csdnimg.cn/blog_migrate/34576b5467c6efd87289119380066116.webp?x-image-process=image/format,png)
我这里的代码都是截图 也是希望大家能自己敲一遍 好 接下来我们看打印的日志是怎样的
![](https://i-blog.csdnimg.cn/blog_migrate/2cfc1f0280d71db26338896edd7265d1.webp?x-image-process=image/format,png)