You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
android-notes/blogs/Android/口水话/四大组件的启动流程口水话.md

3.8 KiB

四大组件的启动流程口水话

目录

  1. Activity
  2. Service
  3. BroadcastReceiver
  4. ContentProvider

Activity 的启动流程

当我们在桌面点击一个应用程序的快捷图标时,Launcher 组件的成员函数 startActivitySafely 就会被调用来启动这个应用程序根 Activity。其中要启动的 MainActivity 信息就包含在 Intent 中。

Launcher 组件是如何获取这些信息的呢?其实是在系统启动时,PackageManagerService 在安装每一个应用程序的过程中,都会去解析其 Manifest 文件,找到 ACTION_MAIN 和 Category 为 LAUNCHER 的 Activity 组件,最后为这个 Acivity 创建一个快捷图标,当点击这个图标时,就会启动这个应用程序的入口 Activity。

回到 Launcher 的 startActivitySafely 函数中,它会调用其父类的 startActivityForResult 方法,实际上是调用 Instrumentation 的 execStartActivity 方法,这是一个插件化的 Hook 点。在这个方法中会传递三个重要的参数,ApplicationThread、mToken、Intent。ApplicationThread 是一个 Binder 本地对象,AMS 接下来就可以通过它来通知 Launcher 组件进入 Pause 状态,mToken 是一个 Binder 代理对象,它指向 AMS 中的一个 ActivityRecord 的 Binder 本地对象,每一个已经启动的 Activity 组件在 AMS 中都有一个对应的 ActivityRecord 对象,用来维护对应的 Activity 组件的运行状态及信息,这样 AMS 就可以获取 Launcher 组件的详细信息了。

在 Instrumentation 的 execStartActivity 中,通过 ActivityManagerNative 的 getDefault 获取 AMS 的一个代理对象,实际上就是调用 ServiceManager 的 getService,获取的是一个 IActivityManager 接口,这也是一个 Hook 点。然后就调到了它的实现类 ActivityManagerProxy 中的 startActivity 方法,在这个方法中,就会往 AMS tranact 一个 START_ACTIVITY_TRANSACTION 的请求。

在 AMS 收到这个请求时,就会让 ActivityStack 去处理。它首先根据上面传递过来的 ApplicationThread 去通知 Launcher 所在的应用程序进程去暂停 Launcher 组件,也就是回调到 ActivityThread 的内部类 ApplicationThread 的 schedulePauseActivity,往主线程发送一个 PAUSE_ACTIVITY 消息,mH 进行处理执行 handlePauseActivity。这个方法先调用 Activity 的 onPause 函数,然后执行 QueuedWork 里面的一些数据写入操作,SharedPreferences 的 apply 就会丢在这执行,如果数据量毕竟大的话可能会造成 ANR 的。最后就是通知 AMS Launcher 组件已经暂停完成了。

再回到 AMS 中,就开始真正的去启动 MainActivity 了,首先检查这个 Activity 对应的 ActivityRecord 对象所在的应用程序进程是否已经存在,如果存在就直接执行 realStartActivityLocked,如果不存在就先 startProcessLocked 去创建一个应用程序进程。创建应用程序进程即调用 Porcess start 函数,并指定该进程的入口函数为 ActivityThread。在它的 main 函数中,创建消息循环,并且调用 attachApplication 把当前的 ApplicationThread 对象传递给 AMS,AMS 有了它就可以去通知应用程序去执行 MainActivity 的 onCreate 方法了。同上述执行 Launcher 的 onPause 函数一样,也是发一个消息给主线程,调用 handleLauncherActivity。

在 handleLauncherActivity 中,通过 Instrumentation 的 newActivity 去创建这个 Activity,然后创建 Application 对象以及 ContextImpl ,最后调用 Activity 的 attach 函数,这个函数里面会 new 一个 PhoneWindow 并关联 WindowManager,也就是 Activity 显示流程的入口函数了。最最后会调用到 Activity 的 onCreate 函数。

至此,Activity 的启动流程讲完了。如果是非根 Activity 的启动呢,只需要去掉创建应用程序进程那一步即可。