ContentProvider相关

一、基本概念:

1.ContentProvider为存储和获取数据提供了统一的接口;
2.使用ContentProvider可以在不同的应用程序之间共享数据;
3.Android为常见的一些数据提供了ContentProvider(包括音频、视频、图片和通讯录等等 )

android平台提供了Content Provider使一个应用程序的指定数据集提供给其他应用程序。这些数据可以存储在文件系统、xml、网络、在一个SQLite数据库、或以任何其他合理的方式,其他应用可以通过ContentResolver类(见ContentProviderAccessApp例子)从该内容提供者中获取或存入数据。

二、contentProvider生命周期

ContentProvider初始化(onCreate)是在Application生命周期方法attachBaseContext之后、onCreate之前

三、contentProvider通信时序

http://gityuan.com/2016/07/30/content-provider/

https://blog.csdn.net/u011733869/article/details/83958712

时序图解读:

1、1~4流程是在APP自己的进程(进程A)中,一般来讲APP在进程启动之后初始化时,就会installProvider(流程7~10),如果APP请求的provider在自己进程,那么到4就能获取到。
2、如果请求的provider另外一个进程(进程B)中,则会触发进程5~6
3、如果进程B不存在则先启动进程B并installprovider(7~10),告诉AMS之后,由AMS返回给进程A对方的provider信息(此过程中由进程A发起的请求provider的线程会一直等待)
4、如果进程B存在则AMS直接返回给进程A对方的provider信息
5、查询到provider信息之后,如果需要跨进程调用,则通过ContentProviderProxy发起binder call到对端进程执行query。
在这其中,AMS充当一个中间管理员的角色,每个进程在启动之后需要把自己应该install的providerinstall之后告诉AMS,这样后面有其他进程请求这个provider的话,AMS可以告诉你所请求的对端的信息。
 

三、ContentProvider线程/进程安全

https://blog.csdn.net/zhanglianyu00/article/details/78362960

ContentProvider的意义在于向其他应用提供数据访问接口。所以ContentProvider的线程安全是跨进程的。那么需要回答两个问题:
当多个应用中的多个线程同时通过注册在系统的某个Provider访问数据的时候,
(1)这些Provider是否同一个实例?
(2)这些对数据库的访问操作在数据提供方的进程中,是并行还是串行?如果是并行,访问操作是原子的吗?

回答:
(1)不管Provider使用方是同一个进程的不同线程,还是不同的进程,Provider方实际上是同一个Provider对象实例。(当然,如果Provider方进程重启了,或者Provider本身或者Binder出现问题重启了,那另当别论)
(2)并发访问时,Provider方query()方法运行在不同的线程,实际上是运行在Provider方的进程的Binder线程池中。


四、框架层原理

ContentProvider的底层是采用 Android中的Binder机制

https://blog.csdn.net/zhanglianyu00/article/details/78390824

4.1、从Provider使用方(Client App)通过getContentResolver()获取到Provider的远程对象,是一个三方的流程:
(1)Client App向AMS获取Provider远程对象;
(2)AMS会检查对应的Provider远程对象有没有发布到AMS,如果有,则直接返回给Client App;如果没有,则启动Provider App进程,并触发Provider App进程安装Provider;
(3)Provider App安装完成Provider之后,会调用AMS发布Provider远程对象到AMS;
(4)AMS将Provider对象返回给Client App。
以上过程中,对于Client App看起来,整个过程是同步的;在AMS中,获取Provider相关的方法都有同步锁,所以这个Provider远程对象实际上是同一个。下图说明这个过程:

Client App获取到Binder远程Provider对象之后,调用其数据操作方法,是在Provider App的Binder线程池中执行。
所以,在Provider层面,系统框架为App做到了Provider的单例,但没有做到Provider的线程安全。这需要在数据层面上自行实现。
对于数据库的场景,Android提供了SQLite。下面要看框架层对于SQLite的线程安全情况。
4.2、SQLiteDatabase/SQLiteOpenHelper线程安全
Android底层集成了SQLite数据库,在框架层,提供了一系列的API辅助访问SQLite数据库。这些类位于android.database.sqlite。
对于数据库,主要有两类操作涉及线程安全:第一、创建/升级/降级数据库;第二、数据的增删改查操作。

4.3、 创建/升级/降级数据库,数据增/删/改/查
SQLiteOpenHelper是Android框架层提供给APP使用的打开SQLite数据库帮助API,常常和Provider捆绑使用。SQLiteOpenHelper在设计上是将数据库创建升降级的逻辑放到实际使用数据库的时候才做,是一种懒加载机制,也正是这样的设计,使得APP可以将这部分逻辑从Provider的onCreate()移到SQLiteOpenHelper的onCreate(),减少Provider.onCreate()的压力。Provider.onCreate()是APP进程在启动的时候执行在主线程。
可以看到,SQLiteOpenHelper.getWritableDatabase()/getReadableDatabase()业务逻辑的实现在另一个方法getDatabaseLocked(),在调用getDatabaseLocked()时候加了自身对象的同步锁。这样一来,数据库创建/升级/降级的逻辑也就被自身对象的同步锁包含。
由于Provider是单例对象,但可能会在多个线程中执行数据操作的方法。那么,如果Provider中使用的是同一个SQLiteOpenHelper实例,是可以保证数据库创建/升级/降级线程安全的。

五、内容提供器(ContentProvider)的安全性

内容提供器是如何做到保证隐私数据不会泄露出去的?

因为内容提供器的良好机制,所有的CRUD操作都一定要匹配到相应的内容URI格式才能进行,而我们当然不可能向UriMatcher中添加隐私数据的URI,所以这部分数据根本无法被外部程序访问到,安全问题也就不存在了。

六、优点

6.1 安全

ContentProvider为应用间的数据交互提供了一个安全的环境:允许把自己的应用数据根据需求开放给 其他应用 进行 增、删、改、查,而不用担心因为直接开放数据库权限而带来的安全问题

6.2 访问简单 & 高效

对比于其他对外共享数据的方式,数据访问方式会因数据存储的方式而不同:

  • 采用 文件方式 对外共享数据,需要进行文件操作读写数据;
  • 采用 Sharedpreferences 共享数据,需要使用sharedpreferences API读写数据

这使得访问数据变得复杂 & 难度大。

  • 而采用ContentProvider方式,其解耦了底层数据的存储方式,使得无论底层数据存储采用何种方式,外界对数据的访问方式都是统一的,这使得访问简单 & 高效

    如一开始数据存储方式 采用 SQLite 数据库,后来把数据库换成 MongoDB,也不会对上层数据ContentProvider使用代码产生影响

Android ContentProvider基本使用

https://www.jianshu.com/p/b62039c0dcae

Android ContentProvider ANR

http://gityuan.com/2016/07/02/android-anr/

https://zhuanlan.zhihu.com/p/141203533

猜你喜欢

转载自blog.csdn.net/cpcpcp123/article/details/115004783
今日推荐