(一) 前言
ContentProvider是android组件之一,可以提供数据的跨应用程序访问,提供数据的跨进程无缝隙访问,所以是非常重要的东东。使用方法一般是
那么下面来提几个问题:
1. 在应用程序A里面怎么跨进程拿到ContentProvider的对象呢?
2. ContentProvider实例对象是保存在哪里呢?
3. ContentProvider的方法实现要注意线程安全吗?
如果你能很清晰的回答这几个问题,那么下面的你就不需要继续看了,如果还有疑问,咱们一起往下面学习吧~
(二) 怎么跨进程拿到ContentProvider的对象
1. 我们来看ContentResolver.query方法是怎么实现的
a. 首先它会去找ContentProvider对象,是这样写的
b. 然后acquireUnstableProvider(uri)方法是这样的:
在这段代码里面,关键地方在这里 String auth = uri.getAuthority();这里取得的auth就是我们在AndroidManifes.xml文件中配置的ContentProvider的android:authorities的值
如:
所以,这个android:authorities属性配置的就是该ContentProvider的名字,是它在Android系统中的名字,我们是通过这个名字去找对应的ContentProvider对象的。
c. ok..既然现在我们拿到ContentProvider的名字了,我们就来看看acquireUnstableProvider方法怎么通过名字来找到ContentProvider对象的。
这个acquireUnstableProvider方法会调用到ActivityThread的acquireProvider方法,这个方法的实现是:
这里就是查找ContentProvider实现的精髓所在了。。
首先,它去找acquireExistingProvider方法,这个方法其实就是根据我们传过来的名称在一个map里面找,如:
ProviderClientRecord pr = mProviderMap.get(name);
由于我们的ActivityThread和我们的应用程序还在一个进程里面,所以这个步骤我们可以理解为:在本地缓存中寻找ContentProvider对象
ok...在本地找了之后,如果找到了,就直接返回。
if (provider != null) {
return provider;
}
如果没有找到,就继续往下面走:
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), name, stable);
这个方法就是调用到ActivityManagerService的getContentProvider方法去寻找ContentProvider.这里是一个跨进程调用,因为ActivityThread和ActivityManagerService不在一个进程里面。
至于ActivityThread和ActivityManagerService的关系,可以参考我以前的这篇帖子:
http://bbs.51cto.com/thread-1008812-1.html
而ActivityManagerService会把所有的ContentProvider都实例化出来,并且缓存在一个map里面,所以我们就可以通过
从ActivityManagerService远程得到一个ContentProvider对象。那么这一步,我们可以理解为:从远程服务中寻找ContentProvider对象
ok..从远程ActivityManagerService得到ContentProvider对象之后,我们继续往下面走。
首先,会调用installProvider方法,这个方法其实就是往本地的ContentProvider map缓存中添加一条缓存记录。
ok...那么这整个过程,我们就可以理解为这样:
i. 第一步,它从ActivityThread里面本地缓存寻找ContentProvider对象,所以找到了,就一切ok..
ii. 第二步,如果第一步没有找到,那么就去ActivityManagerService远程服务中寻找ContentProvider对象。
iii.第三步,从远程服务中找到ContentProvider对象之后,就把这个对象缓存在本地,那么下次找的话,直接就可以从本地缓存中查找了。
那么,它为什么要有这个机制呢?个人猜测:因为跨进程调用是需要时间和资源消耗的,所以,它才有了本地缓存这么个东东。
(三) ContentProvider实例对象是保存在哪里
那么如果大家看完了上面一篇长篇大论,这个问题就很好回答了。
它储存在两个位置:
1. ActivityThread的本地map缓存中
2. ActivityManagerService的远程服务map缓存中
(四) ContentProvider的方法实现要注意线程安全吗
从上面一段描述来看,我们可以发现一个问题,ContentProvider在某种程度上是单例的,比如我们第一次从本地map缓存里面得到ContentProvider对象,第二次我们在同一个应用程序请求的时候,拿到的肯定是同一个缓存对象。
那么我们的ContentProvider的代码,比如查询,更新,删除等等,必须注意线程安全的问题。
那么单例下,我们怎么注意线程安全问题呢?
1. ContentProvider尽量少用成员变量,因为我们用的是单例,所以成员变量是共享的。
2. 所以真的用到了共享资源,建议用synchronized或者TheadLocal来解决。至于synchronized和TheadLocal的区别,这篇文章就不讨论了,下次有机会再写吧。。
相关推荐
android contentprovider使用示例
Android ContentProvider简单实现
详见http://blog.csdn.net/huaxun66/article/details/53202432
免费下载:android ContentProvider详细解析 讲得好详细
android contentprovider
ContentProvider 实例,实现ContentProvider,从其他应用访问ContentProvider数据,实现资源共享
1、Android Room操作SQLite数据 2、ContentProvider使用,使用Room进行数据库操作
通过一个日记本实例讲解了android contentprovider的用法。
android ContentProvider 不用应用程序的数据共享,数据的存储方式
Android contentprovider总结
主要介绍了Android ContentProvider的实现及简单实例代码的相关资料,需要的朋友可以参考下
Android中ContentProvider的示例,详细可以参见博客:http://www.cnblogs.com/plokmju/p/android_ContentProvider.html
Android知识点ContentProvider篇
1.适用场景1) ContentProvider为存储和读取数据提供了统一的接口2) 使用ContentProvider,应用程序可以实现数据共享3) android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,...
ContentProvider 与 ContentResovler 进行应用间数据共享
android下对数据库的增删改查 适配listview 对contentprovider的操作使用
Android基于ContentProvider的音乐播放器,通过读取系统多媒体信息,得到储存在外部存储器上的所有音频文件内容,用listview显示歌曲名和歌手信息.并通过mediaPlayer进行播放.该版本只是完成了一个音乐播放器的最简单...
这个demo详细介绍了ContentProvider内容提供者的用法,详细介ContentProvider怎么进行数据处理,等一下用法,代码有注释,简明易懂