基于Android 6.0源码剖析,本文涉及的相关源码:
1 2 3 4 5 6 7 8 9 |
frameworks/base/core/java/android/app/ActivityThread.java frameworks/base/core/java/android/app/ContextImpl.java frameworks/base/core/java/android/app/IActivityManager.java frameworks/base/core/java/android/content/ContentResolver.java frameworks/base/services/core/java/com/android/server/am/ContentProviderRecord.java frameworks/base/core/java/android/content/IContentProvider.java frameworks/base/core/java/android/content/ContentProvider.java frameworks/base/core/java/android/content/ContentProviderNative.java |
一、概述
ContentProvider(内容提供者)用于提供数据的统一访问格式,封装底层的具体实现。对于数据的使用者来说,无需知晓数据的来源是数据库、文件,或者网络,只需简单地使用ContentProvider提供的数据操作接口,也就是增(insert)、删(delete)、改(update)、查(query)四个过程。
1.1 ContentProvider
ContentProvider作为Android四大组件之一,并没有Activity那样复杂的生命周期,只有简单地onCreate过程。ContentProvider是一个抽象类,当实现自己的ContentProvider类,只需继承于ContentProvider,并且实现以下六个abstract方法即可:
- onCreate():执行初始化工作;
- insert(Uri, ContentValues):插入新数据;
- delete(Uri, String, String[]):删除已有数据;
- update(Uri, ContentValues, String, String[]):更新数据;
- query(Uri, String[], String, String[], String):查询数据;
- getType(Uri):获取数据MIME类型。
1.2 Uri
从ContentProvider的数据操作方法可以看出都依赖于Uri,对于Uri有其固定的数据格式,例如:content://com.gityuan.articles/android/3
- 前缀:默认开头
content://
; - 授权:唯一标识
com.gityuan.articles
; - 路径:指定数据类别以及数据项
/android/3
;
1.3 ContentResolver
其他app或者进程想要操作ContentProvider
,则需要先获取其相应的ContentResolver
,再利用ContentResolver类来完成对数据的增删改查操作,下面列举一个查询操作,查询得到的是一个Cursor
结果集,再通过操作该Cursor便可获取想要查询的结果。
1 2 3 4 5 |
ContentResolver cr = getContentResolver(); //获取ContentResolver Uri uri = Uri.parse("content://com.gityuan.articles/android/3"); Cursor cursor = cr.query(uri, null, null, null, null); //执行查询操作 ... cursor.close(); //关闭 |
1.4 类图
二、流程分析
接下来,从源码角度来说说,以数据查询query
的为例来说说ContentProvider的整个完整流程。
2.1 相关成员变量
在开始源码分析之前,先说说涉及到的几个关于contentProvider的重要的成员变量。
2.1.1 AMS
1 2 3 4 5 6 |
//位于ActivityManagerService.java static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000; static final int CONTENT_PROVIDER_RETAIN_TIME = 20*1000; final ProviderMap mProviderMap; final ArrayList<ContentProviderRecord> mLaunchingProviders = new ArrayList<ContentProviderRecord>(); |
CONTENT_PROVIDER_PUBLISH_TIMEOUT
: 对于attached进程,用于publish该进程中的ContentProvider的超时时长为10s,超过10s则会被hung住。CONTENT_PROVIDER_RETAIN_TIME
: 保持ContentProvider所在进程的上次活动状态的持续时长为20s,当超过20s则运行其下降到正常的 cached LRU列表, 这样做的目的是为了避免在低内存情况下,ContentProvider所在进程发生波动。mProviderMap
:记录所有的contentProvidermLaunchingProviders
:记录所有的存在client等待其发布完成的contentProvider列表,一旦发布完成则相应的contentProvider便会从该列表移除;
2.1.2 ProcessRecord
1 2 3 |
//位于ProcessRecord.java final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>(); final ArrayList<ContentProviderConnection> conProviders = new ArrayList<>(); |
pubProviders
:记录进程中所有创建的ContentProvider;conProviders
:记录进程中所有使用的ContentProvider;
2.1.3 ActivityThread
1 2 3 4 5 6 7 8 9 |
//位于 ActivityThread.java final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap = new ArrayMap<ProviderKey, ProviderClientRecord>(); final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap = new ArrayMap<IBinder, ProviderRefCount>(); final ArrayMap<IBinder,>>(); final ArrayMap<IBinder,tax crayon-theme-github crayon-font-monaco crayon-os-pc print-yes notranslate" data-settings=" minimize scroll-always" style=" margin-top: 12px; margin-bottom: 12px; font-size: 13px !important; line-height: 15px !important;">
一、概述ContentProvider(内容提供者)用于提供数据的统一访问格式,封装底层的具体实现。对于数据的使用者来说,无需知晓数据的来源是数据库、文件,或者网络,只需简单地使用ContentProvider提供的数据操作接口,也就是增(insert)、删(delete)、改(update)、查(query)四个过程。 1.1 ContentProviderContentProvider作为Android四大组件之一,并没有Activity那样复杂的生命周期,只有简单地onCreate过程。ContentProvider是一个抽象类,当实现自己的ContentProvider类,只需继承于ContentProvider,并且实现以下六个abstract方法即可:
1.2 Uri从ContentProvider的数据操作方法可以看出都依赖于Uri,对于Uri有其固定的数据格式,例如:
1.3 ContentResolver其他app或者进程想要操作
1.4 类图二、流程分析接下来,从源码角度来说说,以数据查询 2.1 相关成员变量在开始源码分析之前,先说说涉及到的几个关于contentProvider的重要的成员变量。 2.1.1 AMS
2.1.2 ProcessRecord
2.1.3 ActivityThread
|