9 四大组件的工作过程
本章的意义在于加深对四大组件工作方式的认识,有助于加深对Android整体的体系结构的认识。很多情况下,只有对Android的体系结构有一定认识,在实际开发中才能写出优秀的代码。 读者对四大组件的工作过程有一个感性的认识并且能够给予上层开发一些指导意义。
9.1 四大组件的运行状态
- Activity是一种展示型组件,用于向用户直接地展示一个界面,并且可以接收用户的输入信息从而进行交互,扮演的是一个前台界面的角色。
- Service是一种计算型组件,在后台执行一系列计算任务。它本身还是运行在主线程中的,所以耗时的逻辑仍需要单独的线程去完成。
- BroadcastReceiver是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息。
- ContentProvider是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。其内部的增删改查四大方法是在Binder线程池中被调用的。
9.2 Activity的工作过程
主要分析Activity启动流程。
- Activity的所有
startActivity重载方法最终都会调用startActivityForResult。 - 调用
mInstrumentation.execStartActivity.execStartActivity()方法。 - 在execStartActivity方法内,真正启动Activity由
ActivityManagerNative.getDefault()的startActivity方法实现。 - ActivityManagerNative继承
Binder并实现IActivityManager这个Binder接口。具体实现是ActivityManagerService。 - 所以Activity的启动过程实际上在AMS中:
checkStartActivityResult ()方法检查启动Activity的结果(包括检查有无在manifest注册)startActivity()方法将Activity的启动过程交给一个ActivityStackSupervisor对象mStackSupervisor的startActivityMayWait方法。- 最终Activity的启动过程是在
ActivityStackSupervisor和ActivityStack之间传递,如下图。
- 在最后的
ActivityStackSupervisor. realStartActivityLocked()中,调用了app.thread.scheduleLaunchActivity()方法。 这个app.thread是ApplicationThread类型,继承于IApplicationThread是一个Binder类,内部是各种启动/停止 Service/Activity的接口。 - 在ApplicationThread中,
scheduleLaunchActivity()用来启动Activity,里面的实现就是发送一个Activity的消息(封装成从ActivityClientRecord对象)交给Handler处理。这个Handler有一个简洁的名字H。 - 在H的
handleMessage()方法里,通过handleLaunchActivity()方法完成Activity对象的创建和启动。主要完成了如下几件事:- 从ActivityClientRecord对象中获取待启动的Activity组件信息
- 通过
Instrumentation的newActivity方法使用类加载器创建Activity对象 - 通过
LoadedApk的makeApplication方法尝试创建Application对象,通过类加载器实现(如果Application已经创建过了就不会再创建) - 创建
ContextImpl对象并通过Activity的attach方法完成一些重要数据的初始化 - 通过
mInstrumentation.callActivityOnCreate(activity, r.state)方法调用Activity的onCreate方法
9.3 Service的工作过程
Service有两种工作状态:
- 启动状态:执行后台计算
- 绑定状态:用于其他组件与Service交互
9.3.1 Service的启动过程
- Service的启动从
ContextWrapper的startService开始 - 在ContextWrapper中,大部分操作通过一个
ContextImpl对象mBase实现 - 在ContextImpl中,
mBase.startService()会调用startServiceCommon方法,而startServiceCommon方法又会通过ActivityManagerNative.getDefault()(实际上就是AMS)这个对象来启动一个服务。 - AMS会通过一个
ActiveService对象(辅助AMS进行Service管理的类)mServices来完成启动Service:mServices.startServiceLocked()。 - 在mServices.startServiceLocked()最后会调用
startServiceInnerLocked()方法:将Service的信息包装成一个ServiceRecord对象,通过bringUpServiceLocked()方法来处理,bringUpServiceLocked()又调用了realStartServiceLocked()方法,这才真正地去启动一个Service了。 - realStartServiceLocked()方法的工作如下:
app.thread.scheduleCreateService()来创建Service并调用其onCreate()生命周期方法sendServiceArgsLocked()调用其他生命周期方法,如onStartCommand()- app.thread对象是
IApplicationThread类型,实际上就是一个Binder,具体实现是ApplicationThread继承ApplictionThreadNative
- 具体看app.thread.scheduleCreateService():通过
sendMessage(H.CREATE_SERVICE , s),这个过程和Activity启动过程类似,同时通过发送消息给Handler H来完成的。 - H会接受这个CREATE_SERVICE消息并通过ActivityThread的
handleCreateService()来完成Service的最终启动。 - handleCreateService()完成了以下工作:
- 通过ClassLoader创建Service对象
- 创建Service内部的Context对象
- 创建Application,并调用其onCreate()(只会有一次)
- 通过
service.attach()方法建立Service与context的联系(与Activity类似) - 调用service的
onCreate()生命周期方法,至此,Service已经启动了 - 将Service对象存储到ActivityThread的一个ArrayMap中
9.3.2 Service的绑定过程
和service的启动过程类似的:
- Service的绑定是从
ContextWrapper的bindService开始 - 在ContextWrapper中,交给
ContextImpl对象mBase.bindService() - 最终会调用ContextImpl的
bindServiceCommon方法,这个方法完成两件事:- 将客户端的ServiceConnection转化成
ServiceDispatcher.InnerConnection对象。ServiceDispatcher连接ServiceConnection和InnerConnection。- 这个过程通过
LoadedApk的getServiceDispatcher方法来实现,将客户端的ServiceConnection和ServiceDispatcher的映射关系存在一个ArrayMap中。
- 这个过程通过
- 通过AMS来完成Service的具体绑定过程
ActivityManagerNative.getDefault().bindService()
- 将客户端的ServiceConnection转化成
- AMS中,bindService()方法再调用
bindServiceLocked(),bindServiceLocked()再调用bringUpServiceLocked(),bringUpServiceLocked()又会调用realStartServiceLocked()。 - AMS的realStartServiceLocked()会调用
ActiveServices的requrestServiceBindingLocked()方法,最终是调用了ServiceRecord对象r的app.thread.scheduleBindService()方法。 - ApplicationThread的一系列以schedule开头的方法,内部都通过Handler H来中转:scheduleBindService()内部也是通过
sendMessage(H.BIND_SERVICE , s) - 在H内部接收到BIND_SERVICE这类消息时就交给
ActivityThread的handleBindService()方法处理:- 根据Servcie的token取出Service对象
- 调用Service的
onBind()方法,至此,Service就处于绑定状态了。 - 这时客户端还不知道已经成功连接Service,需要调用客户端的binder对象来调用客户端的ServiceConnection中的
onServiceConnected()方法,这个通过ActivityManagerNative.getDefault().publishService()进行。ActivityManagerNative.getDefault()就是AMS*。
- AMS的publishService()交给ActivityService对象
mServices的publishServiceLocked()来处理,核心代码就一句话c.conn.connected(r.name,service)。对象c的类型是ConnectionRecord,c.conn就是ServiceDispatcher.InnerConnection对象,service就是Service的onBind方法返回的Binder对象。 - c.conn.connected(r.name,service)内部实现是交给了
mActivityThread.post(new RunnConnection(name ,service,0));实现。ServiceDispatcher的mActivityThread是一个Handler,其实就是ActivityThread中的H。这样一来RunConnection就经由H的post方法从而运行在主线程中,因此客户端ServiceConnection中的方法是在主线程中被回调的。 - RunConnection的定义如下:
- 继承Runnable接口,
run()方法的实现也是简单调用了ServiceDispatcher的doConnected方法。 - 由于ServiceDispatcher内部保存了客户端的ServiceConntion对象,可以很方便地调用ServiceConntion对象的
onServiceConnected方法。 - 客户端的onServiceConnected方法执行后,Service的绑定过程也就完成了。
- 根据步骤8、9、10service绑定后通过ServiceDispatcher通知客户端的过程可以说明ServiceDispatcher起着连接ServiceConnection和InnerConnection的作用。 至于Service的停止和解除绑定的过程,系统流程都是类似的。
- 继承Runnable接口,
9.4 BoradcastReceiver的工作过程
9.4.1 广播的注册过程
广播的注册分为:
- 静态注册,由PMS(PackageManagerService)完成整个注册过程
- 动态注册,如下图

9.4.2 广播的发送和接收过程
广播的发送有几种:普通广播、有序广播和粘性广播,他们的发送/接收流程是类似的,因此只分析普通广播的实现。
