目录
- ContentProvider概述
- 类图
- 时序图
- 源码解析
- installProvider
- ContentResolver中的CURD
- acquireProvider
- 到AMS获取ContentProvider
- publishContentProvider
- removeDyingProvider
- 总结
1. ContentProvider概述
ContentProvider作为Android四大组件之一,重要性肯定是不言而喻的,顾名思义,内容提供者,其最重要的作用就在于提供了一种跨进程获取数据的方式,provider组件不仅可以自己的进程使用,还可以提供给其他的进程使用,大大方便了不同进程之间的数据交换,本文将详细介绍provider运行的原理。
注:本文基于Android 8.1
2. 类图
看起来涉及到的类非常多,一下有种不知道从何看起的感觉,所以这里对于其中的重点关注部分加上了颜色:
白色:provider运行过程中涉及到的内部类或私有类,一般APP开发过程中不太会涉及
蓝色:APP开发过程中经常会接触到的类
紫色:在system server
进程中provider相关的类
3. 时序图
其中白色部分:发起获取provider的client进程
红色部分:systemserver进程
蓝色部分:提供provider的server进程
时序图解读:
- 1~4流程是在APP自己的进程(进程A)中,一般来讲APP在进程启动之后初始化时,就会installProvider(流程7~10),如果APP请求的provider在自己进程,那么到4就能获取到。
- 如果请求的provider另外一个进程(进程B)中,则会触发进程5~6
- 如果进程B不存在则先启动进程B并installprovider(7~10),告诉AMS之后,由AMS返回给进程A对方的provider信息(此过程中由进程A发起的请求provider的线程会一直等待)
- 如果进程B存在则AMS直接返回给进程A对方的provider信息
- 查询到provider信息之后,如果需要跨进程调用,则通过ContentProviderProxy发起binder call到对端进程执行query
在这其中,AMS充当一个中间管理员的角色,每个进程在启动之后需要把自己应该install的providerinstall之后告诉AMS,这样后面有其他进程请求这个provider的话,AMS可以告诉你所请求的对端的信息。
4. 源码解析
4.1 ActivityThread.installProvider
installProvider,顾名思义就是安装provider,说的通俗一点就是把APP进程中的provider组件封装成对象保存起来,方便使用
在APP的进程启动的时候,handleBindApplication中会触发installProvider:
private void installContentProviders(
Context context, List<ProviderInfo> providers) {
// 此处的provider信息是在AMS启动进程时
// 从manifest收集到的需要install的provider信息
final ArrayList<ContentProviderHolder> results = new ArrayList<>();
for (ProviderInfo cpi : providers) {
// 执行installProvider,注意此处的stable参数默认为true
ContentProviderHolder cph = installProvider(context, null, cpi,
false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
if (cph != null) {
cph.noReleaseNeeded = true;
results.add(cph);
}
}
try {
// install完成之后,要告诉AMS
ActivityManager.getService().publishContentProviders(
getApplicationThread(), results);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
进一步看一下ActivityThread.installProvider的具体实现
private ContentProviderHolder installProvider(Context context,
ContentProviderHolder holder, ProviderInfo info,
boolean noisy, boolean noReleaseNeeded, boolean stable) {
ContentProvider localProvider = null;
IContentProvider provider;
// holder为null表示还没有install过
if (holder == null || holder.provider == null) {
Context c = null;
ApplicationInfo ai = info.applicationInfo;
if (context.getPackageName().equals(ai.packageName)) {
c = context;
} else if (mInitialApplication != null &&
mInitialApplication.getPackageName().equals(ai.packageName)) {
c = mInitialApplication;
} else {
try {
// 创建context
c = context.createPackageContext(ai.packageName,
Context.CONTEXT_INCLUDE_CODE);
} catch (PackageManager.NameNotFoundException e) {
// Ignore
}
}
...
try {
final java.lang.ClassLoader cl = c.getClassLoader();
// 通过反射创建provider对象
localProvider = (ContentProvider)cl.
loadClass(info.name).newInstance();
// 获取IContentProvider对象,用于跨进程binder call
provider = localProvider.getIContentProvider();
if (provider == null) {
Slog.e(TAG, "Failed to instantiate class " +
info.name + " from sourceDir " +
info.applicationInfo.sourceDir);
return null;
}
// provider的attach,其中最重要的是会执行provider的onCreate
localProvider.attachInfo(c, info);
} catch (java.lang.Exception e) {
if (!mInstrumentation.onException(null, e)) {
throw new RuntimeException(
"Unable to get provider " + info.name
+ ": " + e.toString(), e);
}
return null;
}
} else {
provider = holder.provider;
}
// 到这里,provider的对象创建好了,那么接下来需要做的就是数据结构的封装
// 把provider相关信息保存起来
ContentProviderHolder retHolder;
// mProviderMap的key时providerKey,value是ProviderClientReocrd
// 这两个类主要是封装了一些provider的基本信息,可以到上面看一下类图
synchronized (mProviderMap) {
IBinder jBinder = provider.asBinder();
if (localProvider != null) {
ComponentName cname = new ComponentName(info.packageName, info.name);
// mLocalProvidersByName的key是component信息,value是对应的ProviderClientReocrd
ProviderClientRecord pr = mLocalProvidersByName.get(cname);
if (pr != null) {
// 不为空代表install过
provider = pr.mProvider;
} else {
// 对于新创建的provider,创建其对应的ContentProviderHolder对象
holder = new ContentProviderHolder(info);
holder.provider = provider;
holder.noReleaseNeeded = true;
// install Authorities
pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
// mLocalProviders的key是IContentProvider的binder对象,value是ProviderClientRecord
// 将封装好的provider放入map中
mLocalProviders.put(jBinder, pr);
mLocalProvidersByName.put(cname, pr);
}
retHolder = pr.mHolder;
} else {
// mProviderRefCountMap的key是binder对象,value是ProviderRefCount
// ProviderRefCount中记录了这个provider的stable和unstable的数量
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if (prc != null) {
if (!noReleaseNeeded) {
incProviderRefLocked(prc, stable);
try {
ActivityManager.getService().removeContentProvider(
holder.connection, stable);
} catch (RemoteException e) {
}
}
} else {
ProviderClientRecord client = installProviderAuthoritiesLocked(
provider, localProvider, holder);
if (noReleaseNeeded)