Android 四大组件的工作过程(Android开发艺术探索随笔)

四大组件的运行状态

Android的四大组件中除了BroadcastReceiver以外,其他三种组件都必须在AndroidManifest中注册,对于BroadcastReceiver来说,他即可在AndroidManifest中注册也可以通过代码来注册。在调用方式上,Activity、Service和BroadcastReceiver需要借助Intent,而ContentProvider则无需借助Intent。

  • Activity
    Activity是一种展示型组件,用于向用户直接地展示一个界面,并且可以接受用户的输入信息从而进行交互。只有一种运行模式,叫启动状态。
  • Service
    Service是一种计算型组件,用于在后台执行一系列计算任务。Service组件工作在后台。有两种状态:启动状态和绑定状态。当Service处于启动状态时,这是可以做一些后台计算,并不需要和外界有直接交互。(还是运行在主线程中的,耗时操作还是需要运行在子线程中的)。当Service处于绑定状态时,可以很方便的进行和外界通信。
  • BroadcastReceiver
    是一种消息型组件,用于在不同的组件乃至不同的应用之间传递消息。同样无法被用户感知。有2中注册方式,静态注册(配置文件,应用不启动也可以接受到广播)和动态注册(regist…),
  • ContentProvider
    是一种数据共享型组件,用于向其他组件乃至其他应用共享数据。无法被用户感知。ContentProvider内部的几个方法需要处理好线程同步,因为这几个方法是在Binder线程池中被调用的。

Activity的工作过程

  • 从Activity#satrtActivity开始说起。startActivity最终会调用到startActivityForResult()中。
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }

            cancelInputsAndStartExitTransition(options);
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

mParent代表的是ActivityGrop,ActivityGroup最开始被用来在一个界面中嵌入多个Activity,在API13中被废弃,推荐使用Fragment。
mMainThread.getApplicationThread()得到的是一个Applicatin对象,是ActivityThread的一个内部类 。

  • execStartActivity
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第1张图片,从代码中可以看到,真正启动的方法是
ActivityManagerNative.getDefault()


可以 看到,得到一个Binder对象。
ActivityManagerService继承自ActivityManagerNative,所以AMS也是一个Binder。

ActivityManagerNative.getDefault 实际上得到的是AMS,
我们在回过头来看Instrumentation#execStartActivity中的checkStartActivityResult(..)方法。也就是Instrumentation#checkStartActivityResult方法。方法见下图。
,恩 很明白,就是检查下启动结果,如果错误的话抛出一些对应的异常。

  • ActivityManagerService#startActivity(ActivityManagerNative.getDefault()
    .startActivity)

调用startActivityAsUser(),这个函数代码如下。
Android 四大组件的工作过程(Android开发艺术探索随笔)_第2张图片
其中mStackSupervisor是ActivityStackSupervisor对象。(从字面上看是activity栈的管理员)

  • ActivityStackSupervisor#startActivityMayWait
    关键代码如下

Android 四大组件的工作过程(Android开发艺术探索随笔)_第3张图片

startActivityLocked方法太长了,就不贴了,他里面会调用startActivityUncheckedLocked方法。这个方法还是那么 长,在这个方法中会调用ActivityStack#resumeTopActivitiesLocked

  • ActivityStack#resumeTopActivitiesLocked
    调用这调用着,就到了resumeTopActivitiesLocked
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第4张图片
    重点是
result = resumeTopActivityInnerLocked(prev, options)

这个方法长,我就贴下关键那一句了。

看看,又回到ActivityStackSupervisor了。

  • ActivityStackSupervisor#startSpecificActivityLocked
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第5张图片
realStartActivityLocked(r, app, andResume, checkConfig);

听名字好像是要真的startActivity了。

  • ActivityStackSupervisor#realStartActivityLocked
    代码片段。

这里的app.Thread就是IApplicationThread,这是个接口,他的实现类是ActivityThread的内部类ApplicationThread,如图

饶了这么长的一圈,还是回到ActivityThread中了。

  • ActivityThread#scheduleLaunchActivity

    ,最后一句,发送了个消息。在handlerMessage中。如下

    调用handleLaunchActivity方法。
  • ActivityThread#handleLaunchActivity方法
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第6张图片

看到Activity a = per….,终于到了。

  • ActivityThread#performLaunchActivity
    那么。这个方法中干了什么呢。

    1. 从ActivityClientRecord中获取待启动的Activity的组件信息。
      Android 四大组件的工作过程(Android开发艺术探索随笔)_第7张图片
    2. 通过Instrumentation的newActivity方法是用类加载器创建Activity对象
      Android 四大组件的工作过程(Android开发艺术探索随笔)_第8张图片
    3. 通过LoadedApk的makeApplication方法来尝试创建Application对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
  1. 创建ContextImpl对象并通过Activity的attach方法来完成一个重要数据的初始化
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第9张图片

    1. 调用Activity的onCreate方法。

我去,到这里就完了,整个过程真是极其复杂,让我静下来在看看。哎,这里给出一篇博客来供大家学习。凯子哥

Service的工作过程

Service的启动过程

  • ContextWrapper#startService
@Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

这里的这个mBase是Context类型,而Context是个抽象类,他的实现类是ContextImpl,so,我们去看ContextImpl#startService(service)

  • ContextImpl#startService
@Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }

这里调用了startServiceCommon方法。

  • ContextImpl#startServiceCommon
private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess();
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), getOpPackageName(), user.getIdentifier());
            if (cn != null) {
                if (cn.getPackageName().equals("!")) {
                    throw new SecurityException(
                            "Not allowed to start service " + service
                            + " without permission " + cn.getClassName());
                } else if (cn.getPackageName().equals("!!")) {
                    throw new SecurityException(
                            "Unable to start service " + service
                            + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
    }

哎,有点熟悉,上面有说到过。ActivityManagerNative.getDefault()就是AMS,所以我们转去ActivityManagerService#startService(五个参数)

  • ActivityManagerService#startService(五个参数)

    里面的mService的类型是ActivityService,这是一个辅助AMS进行Service管理的一个类,包括Service的启动、绑定和停止等。
    在ActivityService#startServiceLocked方法中,会调用startServiceInnerLocked方法(返回值为这个函数)0.0
  • ActivityService#startServiceInnerLocked

    ServiceRecord描述的是一个Service记录,ServiceRecord一直贯穿着整个Service的启动过程。这个函数中将Service的启动工作交给了bringUpServiceLocked。而在bringUpServiceLocked中调用了realStartServiceLocked(哎,和Activity如出一辙),看一下这个方法里面的关键代码。
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第10张图片,看到,和Activity一样一样的。
  • ActivityThread#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);
        }

,这里发送消息,最后会调用handleCreateService。

  • Activity#handleCreateService
    这个代码就不贴了,主要完成下面几件事
    • 通过类加载器创建Service实例
    • 创建Application对象并调用onCreate方法(Application只会创建一次)
    • 创建ContextImpl对象并通过attch方法建立关联
    • 最后调用Service的onCreate方法并将Service对象存储到ActivityThread的一个列表中
      这样Service就创建完毕了。

Service的绑定过程
依然从ContextWrapper开始,最后会跳转到ContextImpl#bindServiceCommon方法

  • ContextImpl#bindServiceCommon
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第11张图片
    将客户端的ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象(服务的绑定有可能是跨进程的)
    这个过程通过
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), flags);

完成,接着会调用AMS的bindService方法。

  • ActivityManagerService#bindService

    最终会调用ActivityService#bindServiceLocked
  • ActivityService#bindServiceLocked
    在这里调用bringUpServiceLocked->realStartServiceLocked,接下来的过程基本和启动service一样的。

Service有一个特点,当多次绑定的时候onBind方法只会执行一次,除非Service被终止。
还有一个我没记录,懒..

BroadcastReceiver的工作过程

注册过程
静态注册的广播由PMS来完成,我们看动态注册。

  • ContextImpl#registerReceiver
    会调用到registerReceiverInternal方法
  • ContextImpl#registerReceiverInternal方法

    同样AMS的registerReceiver
  • ActivityManagerService#registerReceiver
    方法很长,关键就是把远程的InnerReceiver对象以及IntentFilter对象存储下来。这样就完成了注册过程。

    发送广播

  • ContextImpl#sendBroadcast
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第12张图片
    调用AMS的broadcastIntent

  • ActivityManagerService#broadcastIntent
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第13张图片
    在这里调用broadcastIntentLocked
  • ActivityManagerService#broadcastIntentLocked
    这个方法长,就不贴了,跟着刚哥走一走。3.1新增2个标记位。
    • FLAG_INCLUDE_STOPPED_PACKAGES 广播会发送给停止了的应用
    • FLAG_EXCLUDE_STOPPED_PACKAGES 不会发送给停止了的应用
      在这个方法内部,会根据intent-filter查找出匹配的接受者并添加到队列中,接着BroadcastQueue就会将广播发送给相应的广播接收者。
queue.scheduleBroadcastsLocked();
  • BroadcastQueue#scheduleBroadcastsLocked()
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第14张图片
    这里就是发送个消息。在handlemessage里会调用processNextBroadcast()
  • BroadcastQueue#processNextBroadcast

    系统遍历mParallelBroadcasts,然后调用deliverToRegisteredReceiverLocked发送。在deliverToRegisteredReceiverLocked内部会调用performReceiveLocked方法。
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第15张图片
  • performReceiveLocked
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第16张图片
  • ActivityThread#scheduleRegisteredReceiver
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第17张图片
    到这里就会调用LockedApk.ReceiverDispatcher的perfoemReceive方法。
  • LockedApk.ReceiverDispatcher#perfoemReceive
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第18张图片
    会创建Args(实现了Runnable接口)对象并通过mActivityThread(Handler)的post方法来执行Args的逻辑,


    在run中,调用了onReceive方法。好了,到这里就结束。

ContentProvider的工作过程

ContentProvider的onCreate方法要先于Application的onCreate方法执行。增删该茶的源码不想说了。太累了,只说下AMS中ContentProvider的创建过程把。

  • AMS#attachApplicationLocked
    Android 四大组件的工作过程(Android开发艺术探索随笔)_第19张图片
    调用ActivityThread#bindApplication
  • ActivityThread#bindApplication
    代码片段

    Android 四大组件的工作过程(Android开发艺术探索随笔)_第20张图片
    调用handleBindApplication
  • ActivityThread#handleBindApplication
    这个方法分四个步骤
    • 创建ContextImpl和Instrumentation
    • 创建Application对象
    • 启动当前进程的ContentProvider并调用onCreate方法
    • 调用Application的onCreate方法
      代码代偿,就不贴了,有兴趣的去看源码

总结:发现这4大组件的源码有很多相似之处。分析起来吃力,但是当理解了Activity的原理之后,去理解其他就会好很多。当然,这是在跟着大神走的前提下。
好了,现在我对这些也有点了解了,闪人。

你可能感兴趣的:(源码,android)