第 9 章 四大组件的工作过程
对四大组件的运行状态和工作方式做概括描述
分析四大组件工作过程
9.1 四大组件的运行状态
除了 BroadcastReceiver 外,其他三种组件都必须在 AndroidManifest 中注册。
BroadcastReceiver 既可以在清单文件注册,也可以通过代码注册。
调用方式上,ContentProvider 无需借助 Intent,其他三种需要借助 Intent
Activity 是一个展示型组件,用于向用户展示一个界面,接收用户输入信息进行交互
- 对用户来说 Activity 就是一个 Android 应用的全部(其他三大组件对用户来说都是不可感知的)
- 启动由 Intent 触发。Intent 分为
显式
(明确的指向一个 Activity) 和隐式
(指向一个或多个目标 Activity,也可能 0 个)。 - 具有特定启动模式
- 可以停止(调用 finish() 方法)
- 主要作用:展示一个界面与用户交互,扮演前台界面
Service 是计算型组件,用于在后台执行计算任务。
- 用户无法直接感知
- 两种运行状态:启动状态、绑定状态。启动状态不需要和外界交互;绑定状态外界可以方便与 Service 通信。
- Service 本身运行在主线程,耗时操作需要单独开个线程去做
- 它可以停止,稍复杂,需灵活采用 stopService 和 unBindService 方法
BroadcastReceiver 是消息型组件,在不同的组件或者不同应用间传递消息
- 用户无法感知(工作在系统内部)
- 两种注册方式:
静态注册和动态注册
。静态注册指在清单文件注册,应用安装时会被系统解析,不需要 app 启动就能收到广播;动态注册通过 Context.registerReceiver() 来实现,不需要的时候用 Context.unRegisterReceiver() 来解除广播,必须 app 启动才能注册并接收广播 - 实际开发中通过 Context 的一系列 send 方法发送广播,然后系统发送给相应的广播接收者。发送和接受的匹配通过广播接收者的
<intent-filter>
描述
ContentProvider 是数据共享型组件,向其他组件或其他应用共享数据
- 用户无法直接感知
- 内部实现增删改查操作
- 内部维护一份数据集合。可以是数据库,也可以用任何类型实现,比如 List、Map
- 增删改查需处理线程同步(因为是在 Binder 线程池中被调用的)
- 不需要手动停止
9.2 Activity 的工作过程(基于 api 27 重新分析了一波)
api 27 中,启动流程的调用链跟书中的稍微有点不一样
启动一个新的 Activity 示例:
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)
Activity 的 startActivity 最终会调用
startActivityForResult
,它的实现如下:mParent
代表 ActivityGroup。它最开始被用来在一个页面中嵌入多个子 Activity,(api 13 之后被废弃,推荐用 fragment)mMainThread.getApplicationThread()
参数,类型是 ApplicationThread(ActivityThread 的内部类)。ApplicationThread
和ActivityThread
在 Activity 的启动过程中发挥着重要作用
Instrumentation
的execStartActivity
方法:- 由上可看出,启动 Activity 真正的实现由 ActivityManager.getService() 的 startActivity 方法来完成。 ActivityManagerService(下面简称 AMS)继承自 IActivityManager 这个 Binder 接口,因此 AMS 也是个 Binder,它是 IActivityManager 的具体实现。
AMS 这个 Binder 对象采用单例模式对外提供:
public static IActivityManager getService() { return IActivityManagerSingleton.get(); } private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>() { @Override protected IActivityManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); final IActivityManager am = IActivityManager.Stub.asInterface(b); return am; } };
- checkStartActivityResult 检查启动 Activity 的结果
Activity 的启动过程又转移到了 AMS 中,下边看 AMS 的 startActivity 方法:
- 可以看到 Activity 的启动过程又转移到了
ActivityStarter
的startActivityMayWait
方法中了 - 在
startActivityMayWait
中又调用了startActivityLocked
方法;然后 startActivityLocked 方法中又调用了startActivity 22 参数
方法;然后 startActivity 22 参数方法中又调用了startActivity 9 参数
方法;然后 startActivity 9 参数方法中又调用了startActivityUnchecked
方法;接着 startActivityUnchecked 方法又调用了ActivityStackSupervisor
的resumeFocusedStackTopActivityLocked
方法。 - 这个时候启动过程已经从
ActivityStarter 到 ActivityStackSupervisor
中去了
- 可以看到 Activity 的启动过程又转移到了
接着分析
ActivityStackSupervisor
的resumeFocusedStackTopActivityLocked
方法- 看上边代码,此时启动流程又从
ActivityStackSupervisor 转移到 ActivityStack
中了
- 看上边代码,此时启动流程又从
分析
ActivityStack
的resumeTopActivityUncheckedLocked
方法:- resumeTopActivityUncheckedLocked 调用了
resumeTopActivityInnerLocked
方法,resumeTopActivityInnerLocked 内部又调用了ActivityStackSupervisor
的startSpecificActivityLocked
方法 - 此时启动流程又从
ActivityStack 转移到 ActivityStackSupervisor
- resumeTopActivityUncheckedLocked 调用了
分析
ActivityStackSupervisor
的startSpecificActivityLocked
方法:- 方法内部调用了
realStartActivityLocked
- 方法内部调用了
接着看
ActivityStackSupervisor # realStartActivityLocked
方法,里边有如下一段重要的代码:app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
app.thread
的类型是 IApplicationThread(Binder 接口),它的实现是 ActivityThread 的内部类ApplicationThread
Activity 的启动过程在 ActivityStarter、ActivityStackSupervisor 和 ActivityStack 之间的传递顺序(api-27):
绕了一大圈,Activity 的启动过程最终回到了 ApplicationThread 中。
接着上边流程,继续看
ApplicationThread 的 scheduleLaunchActivity
方法:- 上边方法逻辑很简单,主要是发送一个启动 Activity 的消息交由 Handler 处理。这个 Handler 的名字是
H
- 上边方法逻辑很简单,主要是发送一个启动 Activity 的消息交由 Handler 处理。这个 Handler 的名字是
接着看
sendMessage
方法的最终实现:接下来看 Handler H 对消息的处理:
接着调用了
handleLaunchActivity
方法:- 上边代码可看出,
performLaunchActivity
方法最终完成了 Activity 对象的创建和启动过程,并且 ActivityThread 通过handleResumeActivity
方法来调用被启动的 Activity 的 onResume 这一生命周期方法。
- 上边代码可看出,
performLaunchActivity 主要完成了如下几件事
从 ActivityClientRecord 中获取待启动的 Activity 的组建信息
创建 ContextImpl 对象,通过 Instrumentation 的 newActivity 方法使用类加载器创建 Activity 对象
- ContextImpl 是一个很重要的数据结构,它是 Context 的具体实现,Context 中的大部分逻辑都是由 ContextImpl 来完成的。
通过 LoadedApk 的 makeApplication 方法城市创建 Application 对象
- 上边方法可以看出,如果 Application 已经被创建过了,就不会再重复创建了,这意味着一个应用只有一个 Application 对象。
- Application 对象的创建也是通过 Instrumentation 来完成的(通过类加载器)
- Application 创建完成后,系统会通过 Instrumentation 的 callActivityOnCreate 来调用 Application 的 onCarete 方法
通过 Activity 的 attach 方法来完成一些重要数据的初始化
activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback);
- ContextImpl 是通过 Activity 的 attach 方法来和 Activity 建立关联的
- 在 attach 方法中还会完成 Window 的创建并建立 Activity 和 Window 的关联。这样当 Window 接收到外部输入事件后就可以传递给 Activity
调用 Activity 的 onCreate 方法
mInstrumentation.callActivityOnCreate(activity, r.state);
,到这里,算是分析完 Activity 的整个启动过程了。
9.3 Service 的工作过程
- 启动状态:主要用于执行后台计算
- 绑定状态:主要用于其他组件和 Service 的交互
- 两种状态可以共存。可以同时处于启动状态和绑定状态
9.3.1 Service 的 启动过程
启动 Service 的示例代码:
val intent = Intent(this, MyService::class.java)
startService(intent)
下面是从 startService 开始追踪的调用链流程图(api-27):
调用链流程中的源代码的分析:
ContextWrapper#startService()
- 上面代码的
mBase
类型是ContextImpl
,Activity 被创建时通过 attach 方法将一个 ContextImpl 对象关联起来,这个 ContextImpl 就是 mBase。 - ContextWrapper 的实现大部分都是通过 ContextImpl 来实现的,在设计模式中这种叫桥接模式
- 上面代码的
ContextImpl#startService()
和ContextImpl#startServiceCommon()
- startService 方法调用 startServiceCommon 方法
- startServiceCommon 方法内部调用 AMS 的 startService 方法(IPC通信)
ActivityManagerService#startService()
- AMS 通过 mServices 这个对象来完成 Service 后续的启动流程。
- mServices 类型是 ActiveServices。ActiveServices是辅助 AMS 进行 Service 管理的类。包括启动、绑定、停止等
- 在
startServiceLocked
方法尾部会调用startServiceInnerLocked
方法
ActiveServices#startServiceInnerLocked()
ServiceRecord
描述的是一个 Service 记录,它一直贯穿着整个 Service 的启动过程- startServiceInnerLocked 又调用
bringUpServiceLocked
方法处理启动工作。在bringUpServiceLocked
方法中又调用realStartServiceLocked
方法。
ActiveServices#realStartServiceLocked()
- 先通过 app.thread 的 scheduleCreateService 方法创建 Service 并调用其 onCreate。(IPC)
- 接着通过 sendServiceArgsLocked 调用 Service 的其他方法。如 onStartCommand。(IPC)
- app.thread 就是 ActivityThread 的内部类 ApplicationThread
ApplicationThread#scheduleCreateService()
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); }
- 跟 Activity 的启动过程类似,都是通过发消息给 Handler H 来完成的。
- H 接受
CREATE_SERVICE
,并调用ActivityThread#handleCreateService
来完成 Service 的最终启动
ActivityThread#handleCreateService()
- 通过类加载器创建 Service 的实例
- 创建 ContextImpl对象
- 尝试创建 Application 对象并调用 onCreate。(Application 一个 app 只有一个)
- 调用 Service 的 attach 方法,建立与 ContextImpl 的连接以及一些其他操作
- 调用 Service 的 onCreate 方法,并将 Service 对象存储到 ActivityThread 的一个列表中。
到此 Service 的启动过程就结束了
ActivityThread 中还会通过 handleServiceArgs 方法调用 Service 的 onStartCommand 方法:
9.3.2 Service 的绑定过程
也是从 ContextWrapper 开始的
ContextWrapper#bindService()
@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); }
- 过程和 Service 启动过程类似。ContextImpl#bindService 最终调用 bindServiceCommon 方法
ContextImpl#bindServiceCommon
主要完成两件事:
将客户端 ServiceConnection 对象转化成 ServiceDispatcher.InnerConnection 对象
- 因为服务的绑定可能是跨进程的,ServiceConnection 必须借助 Binder 才能让远程服务端回调自己的方法。而 ServiceDispatcher.InnerConnection 刚好充当 Binder 角色
- ServiceDispatcher 起着连接 ServiceConnection 和 InnerConnection 的作用
- 看 LoadedApk 的 getServiceDispatcher 方法:
public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags) { synchronized (mServices) { LoadedApk.ServiceDispatcher sd = null; ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); if (map != null) { if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c); sd = map.get(c); } if (sd == null) { sd = new ServiceDispatcher(c, context, handler, flags); if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c); if (map == null) { map = new ArrayMap<>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } return sd.getIServiceConnection(); } }
mService
是一个 ArrayMap,存着应用当前活动的 ServiceConnection 和 ServiceDispatcher 的映射关系,定义如下:private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices = new ArrayMap<>();
getServiceDispatcher
方法里,系统先查找是否有相同的 ServiceConnection,如果不存在就重新创建并保存在 mServices 中对应的当前应用的活动 Map 中。映射关系 key 是 ServiceConnection、value 是 ServiceDispatcher。在
ServiceDispatcher
内部又保存了 ServiceConnection 和 InnerConnection 对象。当 Service 和客户端建立连接后,系统会通过 InnerConnection 调用 ServiceConnection 的 onServiceConnected 方法,这个过程有可能跨进程
通过 AMS 来完成 Service 的具体绑定过程
ActivityManagerService#bindService()
AMS 会调用 ActivityServices 的 bindServiceLocked 方法,bindServiceLocked 再调用 bringUpServiceLocked,到这里就跟 Service 启动流程重合了。
和启动流程不同的是,Service 的绑定过程会调用 app.thread 的 scheduleBindService 方法,这个过程的实现在 ActiveServices 的 requestServiceBindingLocked 方法中。现在再来看一下 ActiveServices 的 realStartServiceLocked 方法:
ActiveServices#requestServiceBindingLocked()
调用了 ApplicationThread 的 scheduleBindService 方法(IPC),然后 ApplicationThread 通过 Handler H 再调用 ActivityThread 的 handleBindService 方法。
ActivityThread#handleBindService()
- 根据 Service 的 token 取出 Service 对象
- 调用 Service 的 onBind 方法,返回一个 Binder 对象给客户端使用
- onBind 调用后已经处于绑定状态了,但这时候客户端不知道已经连接成功了,所以必须调用客户端的 ServiceConnection 的 onServiceConnected。这个过程由 AMS 的 publishService 完成
ActivityManagerService#publishService()
ActiveServices#publishServiceLocked()
其中 c 的类型是 ConnectionRecord,c.conn de类型是 ServiceDispatcher.InnerConnection,service 就是 onBind 方法返回的 Binder对象。
InnerConnection#connected()
在这里调用了 ServiceDispatcher 的 connected 方法。
ServiceDispatcher#connected()
对于 Service 绑定过程来说,ServiceDispatcher 的 mActivityThread 是一个 Handler,其实它就是 ActivityThread 中的 H。分析得知 mActivityThread 不会为 null。所以 RunConnection 就可以运行在主线程中,由此可知客户端 ServiceConnection 中的方法在主线程被回调的。
ServiceDispatcher#doConnected()
由于 ServiceDispatcher 内部保存了客户端的 ServiceConnection 对象,因此可以很方便的调用它的 onServiceConnected 方法
9.4 BroadcastReceiver 的工作过程
- 注册过程
- 发送和接收过程
广播接收者实现示例:
- 定义广播接收者
注册广播接收者
- 静态注册
- 动态注册
发送广播
9.4.1 广播的注册过程
注册分为静态个动态。静态注册在应用安装时系统自动完成注册,具体来说是由 PMS(PackageManagerService) 来完成整个注册过程的。
除了广播以外其他三大组件也是应用安装时由 PMS 解析并注册的
广播动态注册源码调用链:
ContextWrapper#registerReceiver()
这里
mBase
的类型是 ContextImpl(前边介绍过)ContextImpl 的 registerReceiver 方法调用了自己的 registerReceiverInternal 方法
ContextImpl#registerReceiverInternal()
上边代码系统首先从 mPackageInfo 获取 IIntentReceiver 对象,然后再采用跨进程的方式向 AMS 发送广播注册请求。
用 IIntentReceiver 而不用 BroadcastReceiver 是因为广播注册过程是跨进程通信。
IIntentReceiver 必须是一个 Binder 接口,它的具体实现是 LoadedApk.ReceiverDispatcher.InnerReceiver,ReceiverDispatcher 的内部同时保存了 BroadcastReceiver 和 InnerReceiver,这样当接收到广播时,可以方便地调用 BroadcastReceiver 的 onReceive 方法。
LoadedApk#getReceiverDispatcher()
getReceiverDispatcher 方法重新创建了一个 ReceiverDispatcher 对象并将其保存的 InnerReceiver 对象作为返回值返回。
ActivityManagerService#registerReceiver()
把远程的 InnerReceiver 对象以及 IntentFilter 对象存储起来。这样整个广播注册流程就完成了
9.4.2 广播的发送和接收过程
通过 send 方法发送广播时,AMS 会查找出匹配的广播接收者并将广播发送给他们处理。
广播的发送有几种类型:普通广播、有序广播、粘性广播。
这里只分析普通广播(无序广播)的实现
广播的发送和接收本质上是一个过程的两个阶段。从发送开始分析:
ContextWrapper 的 sendBroadcast 方法,调用
ContextImpl#sendBroadcast()
ActivityManagerService#broadcastIntent()
ActivityManagerService#broadcastIntentLocked()
在方法的最开始有如下一行:
// By default broadcasts do not go to stopped apps. intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
表示在 api 27 里默认情况广播不会发给已经停止的应用,从 android 3.1 开始广播就已经有这种特性了。
两个标记位用来表示广播是否要对停止状态的应用起作用:
FLAG_INCLUDE_STOPPED_PACKAGES
表示包含已经停止的应用,广播会发送给已经停止的应用
FLAG_EXCLUDE_STOPPED_PACKAGES
表示不包含已经停止的应用,广播不会发送给已经停止的应用
应用的停止状态:
安装后未运行
被手动或其他应用强停了
若要处在停止状态的应用接收到广播,再发广播的时候设置
FLAG_INCLUDE_STOPPED_PACKAGES
标记位就可以了。两种标记位共存时,以FLAG_INCLUDE_STOPPED_PACKAGES
为准在 broadcastIntentLocked 方法内部会根据 intent-filter 查找出匹配的广播接收者并经过一系列的条件过滤,最终会将满足条件的广播接收者添加到 BroadcastQueue 中,接着 BroadcastQueue 就会将广播发送给相应的广播接收者:
BroadcastQueue#scheduleBroadcastsLocked()
没有立即发送广播,而是发了一个
BROADCAST_INTENT_MSG
消息,BroadcastQueue 收到消息后调用processNextBroadcast
方法BroadcastQueue#processNextBroadcast()
这里只看对普通广播处理的这部分代码:
无需广播存储在
mParallelBroadcasts
中,系统会遍历 mParallelBroadcasts 并将其中的广播发送给它们所有的接收者。具体发送过程是通过 deliverToRegisteredReceiverLocked 方法实现的,它负责将一个广播发送给一个特定的接收者,它内部调用了
performReceiveLocked
来完成具体的发送过程BroadcastQueue#performReceiveLocked()
这里调用了 ApplicationThread 的 scheduleRegisteredReceiver 进行进一步处理
ApplicationThread#scheduleRegisteredReceiver()
调用了 InnerReceiver 的 performReceive 方法,performReceive 方法又会调用
LoadedApk.ReceiverDispatcher
的performReceive
方法LoadedApk.ReceiverDispatcher#performReceive()
上边代码创建一个 Args 对象并通过 mActivityThread 的 post 方法来执行 Args 中的逻辑。Args 实现了 Runnable 接口。
mActivityThread 是 ActivityThread 中的 Handler H,这意味着 Args 里边的逻辑会在主线程执行,即 广播接收者的 onReceive 方法
LoadedApk.ReceiverDispatcher.Args#getRunnable()
关键代码:
final BroadcastReceiver receiver = mReceiver; receiver.setPendingResult(this); receiver.onReceive(mContext, intent);
这时候 BroadcastReceiver 的 onReceive 执行了,意味着应用已经收到广播了,流程结束
9.5 ContentProvider 的工作过程
是内容共享型组件,通过 Binder 向其他组件乃至其他应用提供数据。
当 ContentProvider 所在的进程启动时,ContentProvider 会同时启动并被发布到 AMS 中。
ContentProvider 的 onCreate 要先于 Application 的 onCreate 而执行,这在四大组件中是少有现象。
当一个应用启动时,入口方法为
ActivityThread 的 main 方法
:创建 ActivityThread 的实例并调用它的 attach 方法;创建主线程的消息队列
sMainThreadHandler
,其实是 Handler H。ActivityThread#attach()
远程调用 AMS 的 attachApplication 方法并将 ApplicationThread 对象提供给 AMS。
ApplicationThread 是一个 Binder 对象,它的 Binder 接口是 IApplicationThread,主要用于 ActivityThread 和 AMS 之间的通信。
ActivityManagerService#attachApplication()
thread.bindApplication(processName, appInfo, providers, app.instr.mClass, profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial);
它内部会跨进程调用 ApplicationThread 的 bindApplication 方法,bindApplication 方法会通过 Handler H 切换到 ActivityThread 调用 handleBindApplication 方法
ActivityThread#handleBindApplication()
- 创建 ContextImpl 和 Instrumentation;
- 调用 LoadedApk 的 makeApplication 方法创建 Application 对象;
调用 installContentProviders 方法加载 ContentProvider;
installContentProviders
方法完成了 ContentProvider 的启动工作,它的实现如下所示:上边代码遍历当前进程的 PeoviderInfo 的列表并一一调用 installProvider 方法来启动它们,接着将已经启动的 ContentProvider 发送到 AMS 中,AMS 会把它们存储在 ProviderMap 中,这样一来外部调用者就可以直接从 AMS 中获取 ContentProvider 了。
在
installProvider
有这么一段代码:类加载器完成了 ContentProvider 的创建;attachInfo 方法用来调用它的 onCreate 方法。
ContentProvider 已经被创建并且其 onCreate 也已经被调用,意味着启动流程结束了
通过 Instrumentation 的 callApplicationOnCreate 方法去调用 Applicaton 的 onCreate 方法。
流程图:
启动后,外界就可以通过它提供的增删改查接口去操作 ContentProvider 里边的数据源。这四个方法都是通过 Binder 来调用的。外界只能通过 AMS 根据 Uri 来获取它对应的 Binder 接口 IContentProvider(具体实现是 ContentProvider.Transport)。
一般 ContentProvider 都是单实例的。android:multiprocess
属性决定是否是单实例,默认是 false,即单实例。如果是多实例的话,每个调用者进程都存在一个 ContentProvider 对象。实际开发中没有多实例的应用场景,因此可以简单认为 ContentProvider 都是单实例的。
通过 ContentResolver 访问 ContentProvider 的流程
getContext().getContentResolver()
获取的是 ApplicationContentResolver
对象,ApplicationContentResolver 继承自 ContentResolver
并实现了它里边的抽象方法。
当 ContentProvider 未启动时,第一次访问它就会触发 ContentProvider 的创建,当然也伴随着 ContentProvider 所在进程的启动。
这里分析 query 方法访问 ContentProvider 的调用链
ContentResolver#query()
首先获取 IContentProvider 对象,不论是通过
acquireUnstableProvider
方法还是acquireProvider
方法获取,最终都会调用ActivityThread#acquireProvider()
方法。ActivityThread#acquireProvider()
如果 ActivityThread 存在目标 ContentProvider 了,就直接返回;如果目标 ContentProvider 没有启动,就通过
ActivityManagerService#getContentProvider()
请求启动目标 ContentProvider,最后再通过installProvider
来修改引用计数。ContentProvider 启动时会伴随着进程的启动,在 AMS 中首先会启动 ContentProvider 所在的进程,然后再启动 ContentProvider。启动进程通过 AMS 的
startProcessLocked
方法来完成,内部主要通过 Process 的 start 方法来完成新进程启动,新进程启动后的入口方法为 ActivityThread 的 main 方法。ContentProvider 的启动流程前边已经分析过了,这里点到即止。个人有一个疑问,进程启动的细节到 ZygoteProcess 这个类之后就完全没头绪了。。以后查查
再看一下 IContentProvider 调用了 query 方法,找一下 IContentProvider 的具体实现,在
ActivityThread#acquireProvider()
方法里,我们看到最后返回了ContentProviderHolder$provider
这个对象;在ActivityThread#installProvider
方法里有这样几行代码:ContentProvider localProvider = null; IContentProvider provider; final java.lang.ClassLoader cl = c.getClassLoader(); localProvider = (ContentProvider)cl. loadClass(info.name).newInstance(); provider = localProvider.getIContentProvider(); holder = new ContentProviderHolder(info); holder.provider = provider;
可以看出,
ContentProvider#getIContentProvider()
方法返回了我们需要的 IContentProvider 对象,再看一下ContentProvider#getIContentProvider()
方法的具体实现:public IContentProvider getIContentProvider() { return mTransport; }
返回的
mTransport
类型是Transport
,所以 IContentProvider 这个 Binder 接口的具体实现是 Transport。看一下Transport#query()
这里直接调用了 ContentProvider 的 query 方法,执行结果再通过 Binder 返回给调用者。到这里流程就全部结束了。