第九章,四大组件的工作过程
四大组件的运行状态
Activity的工作过程
Service的工作过程
BroadCastReceiver工作过程
ContentProvider工作过程
Activity
- 除了
BroadCastReceiver
外,都必须在Manifest
中注册.BroadCastReceiver
可以通过代码或Manifest
注册, - 调用方式上除了
ContentProvider
外,其他组件都需要借助Intent
Intent
分为显示Intent和隐式Intent
.Activity
主要用来展示一个界面
并和用户交互
- 除了
Service
- 一种计算型组件.用于在后台执行一系列计算任务
Service
有启动状态和绑定状态
Service
是运行在主线程
的,耗时的后台任务需要开线程- 处于
绑定状态的Service
,外界可以很方便的和其进行通信 Service
可以通过stopService
和unBindService
停止
- BroadCastReceiver
- 一种消息型组件
- 广播的注册有两种方式,
静态注册
和动态注册
(需要绑定和解绑) 动态注册
的广播需要应用启动才能注册
并接受广播- 广播可以实现低耦合的观察者模式,广播没有停止的概念
- ContentProvider
- 数据共享型组件
ContentProvider
可以通过数据库实现,也可以通过其他方式来实现ContentProvider
除了onCreate
外都运行在Binder线程池
,需要做好同步ContentProvider
不需要停止
Activity工作过程
Activity#startActivityForResult
-> Instrumentation#execStartActivity
-> ActivityManagerNative.getDefault().startActivity(AMS#startActivity)
//ActivityManagerNative继承自Binder并实现了IActivityManager
//ActivityManagerService 继承了ActivityManagerNative,上面的getDefault是通过单例获取到的AMS
除了调用Instrumentation.execStartActivity
除了上面的会调用AMS.startActivity
外,还会检查启动Activity
的结果.比如常见的清单文件没有注册就是在此抛出的.
AMS#startActivity -> ActivityStackSupervisor#startActivityMayWait
-> .. -> ActivityStack#resumeTopActivitiesLocked
-> .. -> ActivityStackSupervisor#realStartActivityLocked
如上经过一系列调用,最终调用到了ActivityStackSupervisor#realStartActivityLocked
方法,进而调用app.thread#scheduleLaunchActivity
.
其中app.thread
的类型为IApplicationThread
,其申明如下:
public interface IApplicationThread extends IInterface
IApplicationThread
是一个Binder
,内部完成了大量Activity和Service
生命周期操作.其实现类是ActivityThread.ApplicationThread
,其申明如下:
private class ApplicationThread extends ApplicationThreadNative{
//...
}
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread{
//和系统生成的AIDL文件作用一致.内部有一个ApplicationThreadProxy类,由于此类是抽象类,故ApplicationThread就成了IApplicationThread的最终实现类
}
绕了一大圈,最终是ApplicationThread.scheduleLaunchActivity
启动Activity.
//ApplicationThread#scheduleLaunchActivity
//通过发送消息来启动Activity
sendMessage(H.LAUNCH_ACTIVITY, r);
这个 H 是 ActivityThread 的内部类.继承了Handler
// H#handleMessage
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
//...
handleLaunchActivity(r, null);
} break;
//ActivityThread#handleLaunchActivity
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent){
//
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
// 调用Activity.onResume生命周期方法/
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
}
}
其中,performLaunchActivity
主要完成了如下几件事
- 从
ActivityClientRecord
中获取待启动的Activity- 通过
Instrumentation.newActivity
方法用类加载器加载Activity对象- 通过
LoadedApk.makeApplication
尝试创建Application对象.(如果已创建,则不会重复创建),进而回调Application#onCreate
.- 创建
ContextImpl
,并调用Activity#attach
完成一些重要数据的初始化.(ContextImpl
通过attach
来和Activity
建立关联,并且在attach
中完成window
的创建,并建立Activity
和window
的关联)- 调用
Activity#onCreate
方法.
Service工作过程
Service启动过程
contextImpl#startService -> contextImpl#startService
-> ActivityManagerNative.getDefault().startService(AMS#startService)
-> mServices#startServiceLocked
mServices是ActiveService
类型,是辅助AMS进行Service管理
的类.
// 经过一系列的调用,最终调用到了realStartServiceLocked
mServices#startServiceLocked -> ...-> realStartServiceLocked.
// 如下两个过程都是IPC过程
realStartServiceLocked -> app.thread#scheduleCreateService(H.sendMessage)
-> Service#onCreate -> sendServiceArgsLocked
-> onStartCommand
- 如上的
app.thread即 ActivityThread.ApplicationThread
,调用过程类似,依旧是调用H.sendMessage
完成Service的启动
ContextImpl
通过Service#attach
建立二者之间的联系.activity#handleServiceArgs
调用Service#onStartCommand
Service绑定过程
contextImpl#bindServie -> contextImpl#bindService ->bindServiceCommon
其中
bindServiceCommon
做了两件事
1. 将客户端ServiceConnection
转化为ServiceDispatcher.InnerConnection
对象.转化是因为服务端的绑定时垮进程的,InnerConnection
刚好充当了Binder
的角色,ServiceDispatcher
连接着InnerConnection
和ServiceConnection
,系统会通过InnerConnection
调用ServiceConnection#onServiceConnected
.
2. 通过AMS完成Service的具体绑定
过程.
AMS#bindService -> ActiveServices#bindServiceLocked
-> realStartServiceLocked //后续过程和Service启动过程类似
-> app.thread#scheduleBindService
-> sendMessage(H.BIND_SERVICE, s)
Handler
接受到消息后,会调用handleBindService
,根据Service的Token取出Service
,并调用Service#onBind
,完成绑定.然而此时客户端并不知道已经连接上了,通过AMS#publishService
需要回调onServiceConnected
通知客户端.
需要注意的是:
1. 对于同一服务, Service
的onBind
和onCreate
都只会执行一次.
2. ServiceConnection
在主线程被回调.其 是一个Runnable
,最终会调用 onServiceConnected
BroadCastReceiver工作过程
广播注册
广播发送和接收
广播的注册
静态注册的广播在应用安装时由系统自动完成注册,即有PMS
来完成
其他三大组件也是通过PMS
解析清单文件来完成注册的.
- 广播的动态注册
contextImpl#registerReceiverInternal
//首先,从mPackageInfo中获取IIntentReceiver,然后跨进程向AMS发送广播注册的请求
//之后调用AMS#registerReceiver
-> ActivityManagerNative.getDefault().registerReceiver
IIntentReceiver
是一个Binder
对象,具体实现类是LoadedApk.ReceiverDispatcher.InnerReceiver
和Service类似,ReceiverDispatcher
内部同时保存了BroadCastReceiver
和InnerReceiver
,AMS#registerReceiver
看起来很长,关键部分就是把远程的InnerReceiver与IntentFilter对象存储起来
,如下所示
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId) {
//...
mRegisteredReceivers.put(receiver.asBinder(), rl);
//...
mReceiverResolver.addFilter(bf);
}
广播的发送和接收
- 当
send
后,AMS
会查找出匹配的广播接收者
,并将广播发送给他们处理
- 广播的发送类型:
普通广播
,有序广播
,粘性广播
- 广播的
发送
和接收
本质是一个过程的两个阶段
contextImpl.sendBroadcast -> ActivityManagerNative.getDefault().broadcastIntent
//向AMS发起一个异步请求发送广播
-> AMS#broadcastIntentLocked
这里有个点需要注意,
1. 从3.1
开始,默认情况下广播不会发给已经停止的应用
2. 在3.1
中已经加入了两个标志位用于控制是否对停止状态应用起作用
FLAG_EXCLUDE_STOPPED_PACKAGES
:不包含
已停止应用
FLAG_INCLUDE_STOPPED_PACKAGES
:包含
已停止应用,两种状态共存时,选择包含
3. 应用停止分为两种:1. 安装未运行,2.被强停了
4. 这个特性会影响开机广播
//根据 intent-filter找出匹配的,添加到BroadcastQueue中,然后发送给接收者
AMS#broadcastIntentLocked->BroadcastQueue.scheduleBroadcastsLocked()
//遍历所有广播,并发送给接收者
-> mHandler.sendMessage -> processNextBroadcast
->... ->
//具体的发送过程
performReceiveLocked
performReceiveLocked
内部依然会调用app.thread
的scheduleRegisteredReceiver
scheduleRegisteredReceiver -> InnerReceiver.performReceive
-> LoadedApk.ReceiverDispatcher.performReceive
-> ActivityThread.post(Args)
其中ActivityThread
就是H
,Args
实现了Runnable
,Args的run
方法中有如下代码片段:
final BroadcastReceiver receiver = mReceiver;
receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);
ContentProvider工作过程
ContentProvider
的onCreate
要先于Application的onCreate
执行.
- 当应用启动时,入口方法是
Activity#main
main
方法中会创建主线程消息队列
ActivityThread#attach
远程调用AMS#attachApplication
,并将ApplicationThread
对象提供给AMS
- 在
AMS#attachApplication
会调用ApplicationThread#bindApplication
ApplicationThread#bindApplication
会经过ActivityThread.mH
切换到ActivityThread
中执行.具体方法就是handleBindApplication
- 在
handleBindApplication
中,ActivityThread
会创建Application
对象,并加载ContentProvider
ActivityThread
会先加载ContentProvider
,后回调Application#onCreate
- 一般来说,
ContentProvider
应该是单实例的,具体需要有它的android:multiprocess
属性决定.(默认为false
)- 如果此属性为
true
,则每个调用者进程中都存在一个ContentProvider
对象- 多实例场景很少.可以
简单认为Contentprovider都是单实例的
访问Contentprovider
需要通过ContentResolver(抽象类)
,通过contex t.getContentResolver
获取的是ApplicationContentResolver
对象.
- ContentProvider的query操作
这里以查询操作为例.首先会通过acquireProvider
来获取IContentProvider
ApplicationContentResolver#acquireProvider
//如果没有ContentProvider启动,就会跨进程请求AMS启动ContentProvider
-> ActivityThread#acquireProvider
启动ContentProvider
,首先会启动其所在的进程
.启动进程由AMS#startProcessLocked
完成.
AMS#attachApplication ->ActivityThread#bindApplication(/*通过发送消息给mH*/)
-> //完成Application及ContentProvider的创建
具体步骤如下:
- 创建
ContextImpl
和Instrumentation
- 创建
Application
- 启动
ContentProvider
并调用其onCreate
- 调用
Application#onCreate