Android 开发艺术探索之---ContentProvider(内容提供者)

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 也是可以工作的  只是它无法向外界提供有效的数据而已


Android 开发艺术探索之---ContentProvider(内容提供者)

然后接着我们需要在功能清单中Manifest中注册 MyContentProvider 如下图所示 其中 android:authorities="star.liuwen.com.endcontentprovider.MyContentProvider" 是ContentProvider中的唯一标识  而process 则是独立进程的标志  


Android 开发艺术探索之---ContentProvider(内容提供者)


Android 开发艺术探索之---ContentProvider(内容提供者)
MainActivuty中的代码

然后我们可以看到打印出来的日志


Android 开发艺术探索之---ContentProvider(内容提供者)

从日志中我们可以看到MyContentProvider 中的query方法被调用了三次 并且三次都是在不同的线程当中  可以看出来  他们都是运行在一个BInder线程当中  而onCreate()方法则是在主线程当中  也就是我们的UI线程

到这里 我们自定义的MyContentProvider 已经跑通了 虽然MyContentProvider 中没有返回任何的数据 所以接下来 我们继续完善 需要MyContentProvider 能够对外提供数据 上面我写了Contetn provider 对底层的数据存储方法没有任何的要求 可以是文件 也可以是SqLite 这里我们简单的用SqLite来实现存储


Android 开发艺术探索之---ContentProvider(内容提供者)
SqLiteHelper数据帮手

上面代码是一个简单的数据库实现 我们借助SqLiteHelper 来管理数据可的创建 支持 和升级 下面我们就要通过MyContentProvider向外界提供数据库中的信息  我们知道 ContentProvider 是通过Uri 来区分外界要访问的数据集合 在本列中支持外界对MyContentProvider 中的book表 和user表进行访问 为了知道外界要访问的是哪个表 我们需要为他们定义单独的Uri 和Uri_code 并将Uri和Uri_code 相关联 我们可以使用UriMatcher的addUrI方法将Uri_code关联到一起 这样 当外界请求访问MyContentProvider 时,我们就可以根据请求的Uri来得到Uri_code 有了Uri_code 我们就可以知道外界想要访问哪个表 然后就可以进行相应的数据操作了 


Android 开发艺术探索之---ContentProvider(内容提供者)
Android 开发艺术探索之---ContentProvider(内容提供者)
Android 开发艺术探索之---ContentProvider(内容提供者)
Android 开发艺术探索之---ContentProvider(内容提供者)

完整代码就是这样的 

下面在看Activity中的 代码


Android 开发艺术探索之---ContentProvider(内容提供者)
Android 开发艺术探索之---ContentProvider(内容提供者)

我这里的代码都是截图 也是希望大家能自己敲一遍 好 接下来我们看打印的日志是怎样的


Android 开发艺术探索之---ContentProvider(内容提供者)
打印日志