您的位置:首页 > 编程语言 > PHP开发

ContentProvider的工作过程

2018-01-04 17:49 225 查看
通过ContentProvider的增删查改四个方法的任何一个都可以触发ContentProvider的启动过程,比如选query方法

1 通过acqureUnstableProvider或acquireProvider方法获取IContentProvider对象,最终的都是通过acquireProvider方法来获取ContentProvider。ApplicationContentResolver的acquireProvider方法

2 ApplicationContentResolver的acquireProvider方法中没有处理任何逻辑,直接调用ActivityThread的acquireProvider方法,可查看其源码

3 在ActivityThread的acquireProvider方法中,先判断是否已经存在目标ContentProvider,若存在则直接返回;若不存在(即没有启动),则发起一个进程间请求给AMS让其启动目标ContentProvider,即调用 ActivityManager.getService().getContentProvider方法,返回一个ContentProviderHolder对象,在调用该对象的provider并将其返回

4 ContentProvider被启动的过程伴随者进程的启动,在AMS中,首先会启动ContentProvider所在的进程,然后再启动ContentProvider。启动进程是由AMS的startProcessLocked方法完成的,其内部主要是通过Process的start方法来完成一个新进程的的启动的,新进程启动后其入口方法是ActivityThread的main方法,

5 Activity的main方法是一个静态方法,它的内部会首先创建ActivityThread的实例并调用attach方法来进行一系列的初始化,接着就开始消息循环了

ActivityThread thread = new ActivityThread();
thread.attach(false);


6 ActivityThread的attach方法会将ApplicationThread对象通过AMS的attachApplication方法跨进程传递给AMS

final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {


7 AMS的attachApplication方法调用了attachApplicationLocked方法

public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}


8 attachApplicationLocked方法调用ApplicationThread的bindApplication,该过程也是进程间通信

9 ActivityThread的bindApplication会发送一个BIND_APPLICATION类型的消息给mH,mH是一个Handler,它收到消息后,会调用ActivityThread的handleBindApplication方法

10 ActivityThread的handleBindApplication则完成了Application的创建以及ContentProvider的创建,可分四个步骤:

1 创建ContextImpl和Instrumentation
2 创建Application
3 启动当前进程的ContentProvider并调用其onCreate方法:
if (!data.restrictedBackupMode) {
if (!ArrayUtils.isEmpty(data.providers)) {
installContentProviders(app, data.providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".                 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
installCotentProviders方法完成了ContentProvider的启动工作。首先遍历当前进程的ProviderInfo的列表并一一调用installProvider方法来启动它们,接着将启动的ContentProvider发布到AMS中,AMS会把它们存储在ProviderMap中,这样外部的调用者就可以直接从AMS中获取ContentProvider了
installProvider中通过类加载器完成ContentProvider对象的创建,还会通过ContetProvider的attachInfo方法来调用ContentProvider的onCreate方法,此时ContentProvider就已经启动
4 调用Application的onCreate方法


经过以上四个步骤,ContentProvider已经启动,并且所在进程的Application也已经启动,然后其他程序就可以通过AMS来方法问这个ContentProvider了,拿到ContentProvider后,就可以通过它提供的接口方法来访问它了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: