开发艺术探索 -- 四大组件的工作过程

来源:互联网 发布:直播系统源码 编辑:程序博客网 时间:2024/05/01 10:52

第九章,四大组件的工作过程

四大组件的运行状态
Activity的工作过程
Service的工作过程
BroadCastReceiver工作过程
ContentProvider工作过程

  • Activity

    1. 除了BroadCastReceiver外,都必须在Manifest中注册.BroadCastReceiver可以通过代码或Manifest注册,
    2. 调用方式上除了ContentProvider外,其他组件都需要借助Intent
    3. Intent分为显示Intent和隐式Intent.
    4. Activity主要用来展示一个界面和用户交互
  • Service

    1. 一种计算型组件.用于在后台执行一系列计算任务
    2. Service启动状态和绑定状态
    3. Service是运行在主线程的,耗时的后台任务需要开线程
    4. 处于绑定状态的Service,外界可以很方便的和其进行通信
    5. Service可以通过stopServiceunBindService停止
  • BroadCastReceiver
    1. 一种消息型组件
    2. 广播的注册有两种方式,静态注册动态注册(需要绑定和解绑)
    3. 动态注册的广播需要应用启动才能注册并接受广播
    4. 广播可以实现低耦合的观察者模式,广播没有停止的概念
  • ContentProvider
    1. 数据共享型组件
    2. ContentProvider可以通过数据库实现,也可以通过其他方式来实现
    3. ContentProvider除了onCreate外都运行在Binder线程池,需要做好同步
    4. 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#handleMessagepublic void handleMessage(Message msg) {            switch (msg.what) {                case LAUNCH_ACTIVITY: {//...                    handleLaunchActivity(r, null);                } break;
//ActivityThread#handleLaunchActivityprivate 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主要完成了如下几件事

  1. ActivityClientRecord中获取待启动的Activity
  2. 通过Instrumentation.newActivity方法用类加载器加载Activity对象
  3. 通过LoadedApk.makeApplication尝试创建Application对象.(如果已创建,则不会重复创建),进而回调Application#onCreate.
  4. 创建ContextImpl,并调用Activity#attach完成一些重要数据的初始化.(ContextImpl通过attach来和Activity建立关联,并且在attach中完成window的创建,并建立Activitywindow的关联)
  5. 调用Activity#onCreate方法.

Service工作过程

Service启动过程

contextImpl#startService -> contextImpl#startService-> ActivityManagerNative.getDefault().startService(AMS#startService)-> mServices#startServiceLocked

mServices是ActiveService类型,是辅助AMS进行Service管理的类.

// 经过一系列的调用,最终调用到了realStartServiceLockedmServices#startServiceLocked -> ...-> realStartServiceLocked.
// 如下两个过程都是IPC过程realStartServiceLocked -> app.thread#scheduleCreateService(H.sendMessage) -> Service#onCreate -> sendServiceArgsLocked -> onStartCommand
  1. 如上的app.thread即 ActivityThread.ApplicationThread,调用过程类似,依旧是调用H.sendMessage完成Service的启动
  2. ContextImpl通过Service#attach建立二者之间的联系.
  3. activity#handleServiceArgs调用Service#onStartCommand

Service绑定过程

contextImpl#bindServie -> contextImpl#bindService ->bindServiceCommon

其中bindServiceCommon做了两件事
1. 将客户端ServiceConnection转化为ServiceDispatcher.InnerConnection对象.转化是因为服务端的绑定时垮进程的,InnerConnection刚好充当了Binder的角色,ServiceDispatcher连接着InnerConnectionServiceConnection,系统会通过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. 对于同一服务, ServiceonBindonCreate 都只会执行一次.
2. ServiceConnection在主线程被回调.其 是一个Runnable,最终会调用 onServiceConnected

BroadCastReceiver工作过程

广播注册
广播发送和接收

广播的注册

静态注册的广播在应用安装时由系统自动完成注册,即有PMS 来完成
其他三大组件也是通过PMS解析清单文件来完成注册的.

  • 广播的动态注册
contextImpl#registerReceiverInternal//首先,从mPackageInfo中获取IIntentReceiver,然后跨进程向AMS发送广播注册的请求//之后调用AMS#registerReceiver-> ActivityManagerNative.getDefault().registerReceiver
  1. IIntentReceiver是一个Binder对象,具体实现类是LoadedApk.ReceiverDispatcher.InnerReceiver
    和Service类似,ReceiverDispatcher内部同时保存了BroadCastReceiverInnerReceiver,
  2. 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);        }

广播的发送和接收

  1. send后,AMS查找出匹配的广播接收者,并将广播发送给他们处理
  2. 广播的发送类型: 普通广播,有序广播,粘性广播
  3. 广播的发送接收本质是一个过程的两个阶段
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.threadscheduleRegisteredReceiver

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工作过程

ContentProvideronCreate要先于Application的onCreate执行.

  1. 当应用启动时,入口方法是Activity#main
  2. main方法中会创建主线程消息队列
  3. ActivityThread#attach远程调用AMS#attachApplication,并将ApplicationThread对象提供给AMS
  4. AMS#attachApplication会调用ApplicationThread#bindApplication
  5. ApplicationThread#bindApplication会经过ActivityThread.mH切换到ActivityThread中执行.具体方法就是handleBindApplication
  6. handleBindApplication中,ActivityThread会创建Application对象,并加载ContentProvider
  7. ActivityThread会先加载ContentProvider,后回调Application#onCreate
  1. 一般来说,ContentProvider应该是单实例的,具体需要有它的android:multiprocess属性决定.(默认为false)
  2. 如果此属性为true,则每个调用者进程中都存在一个ContentProvider对象
  3. 多实例场景很少.可以 简单认为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的创建

具体步骤如下:

  1. 创建ContextImplInstrumentation
  2. 创建Application
  3. 启动ContentProvider并调用其onCreate
  4. 调用Application#onCreate
0 0
原创粉丝点击