绘制流程概览
Android 程序启动 -> Activity 加载并调用生命周期 onCreate -> Activity 调用 setContentView -> UI 绘制
Android 启动流程分析
我们都知道 Android 程序的启动入口是 ActivityThread.main 函数, 那么看一看 main 函数是如何进行启动的.
- ActivityThread.class
- public static void main(String[] args) {
- ...
- ActivityThread thread = new ActivityThread();
- thread.attach(false);
- ...
- }
- private void attach(boolean system) {
- ...
- final IActivityManager mgr = ActivityManager.getService();
- try {
- mgr.attachApplication(mAppThread);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- ...
- }
由上面的源码可知, 我们在 main 函数中做了两件事情:
生成一个 ActivityThread 对象
调用该对象的 attach 方法
在 attach 方法中, 也做了两件事情:
获取了 IActivityManager 的对象实例
执行该对象的 attachApplication 方法
通过 ActivityManager.getService() 获取到 Activity 管理器接口对象, 那么如何拿到的呢? 我们来看下源码实现:
- ActivityManager.class
- /**
- * @hide
- */
- public static IActivityManager getService() {
- return IActivityManagerSingleton.get();
- }
- private static final Singleton<IActivityManager> IActivityManagerSingleton =
- new Singleton<IActivityManager>() {
- @Override
- protected IActivityManager create() {
- final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
- final IActivityManager am = IActivityManager.Stub.asInterface(b);
- return am;
- }
- };
服务管理器通过 getService 拿到了 ActivityService 的 IBinder 对象, 通过跨进程获取到 am 对象.
mgr.attachApplication(mAppThread) 是将 ApplicationThread 和 ActivityManagertService 相关联.
在 App 进程启动之后, AMS 便会跨 binder 调用到 ApplicationThread 的 scheduleLaunchActivity, 启动 Activity.
详细的介绍请参照深入理解 Activity--Token 之旅
通过上面的分析, 我们知道 ApplicationThread 这个对象在启动过程中起着至关重要的作用, 来看下它的源码:
ApplicationThread 类里面都干了什么事情?
- ApplicationThread.class
- private class ApplicationThread extends IApplicationThread.Stub {
- public final void schedulePauseActivity(IBinder token, boolean finished, ...
- public final void scheduleStopActivity(IBinder token, boolean showWindow, ...
- @Override public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident, ...
- ...
如上图所示, 一堆的 schedule 方法, 按照字面翻译, 我们可以猜测出, 这个是在 Activity 状态变化时去调用的方法.
在诸多的 schedule 方法里面, 根据注释得知, scheduleLaunchActivity 是在 Activity 加载的时候调用, 我们来看一下:
- ApplicationThread.class
- // we use token to identify this activity without having to send the
- // activity itself back to the activity manager. (matters more with ipc)
- @Override
- public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
- ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
- CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
- int procState, Bundle state, PersistableBundle persistentState,
- List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
- boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
- updateProcessState(procState, false);
- ActivityClientRecord r = new ActivityClientRecord();
- ...
- updatePendingConfiguration(curConfig);
- sendMessage(H.LAUNCH_ACTIVITY, r);
- }
根据代码我们可以分析
创建了 ActivityClientRecord 对象
将 ActivityClientRecord 对象以及标志位 LAUNCH_ACTIVITY 发送出去
- ApplicationThread.class
- private void sendMessage(int what, Object obj) {
- sendMessage(what, obj, 0, 0, false);
- }
- private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
- if (DEBUG_MESSAGES) Slog.v(
- TAG, "SCHEDULE" + what + " " + mH.codeToString(what)
- + ":" + arg1 + "/" + obj);
- Message msg = Message.obtain();
- msg.what = what;
- msg.obj = obj;
- msg.arg1 = arg1;
- msg.arg2 = arg2;
- if (async) {
- msg.setAsynchronous(true);
- }
- mH.sendMessage(msg);
- }
- final H mH = new H();
- private class H extends Handler {
- ...
- }
通过以上代码可以知道, 将创建的 ActivityClientRecord 对象以及标志位通过 handler 发送出去, 那我们顺着找到 mH 的 handleMessage 方法
- private class H extends Handler {
- ...
- public void handleMessage(Message msg) {
- if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling:" + codeToString(msg.what));
- switch (msg.what) {
- case LAUNCH_ACTIVITY: {
- ...
- final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
- ...
- handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
- ...
- } break;
- ...
- }
- ...
- }
- private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
- ...
- Activity a = performLaunchActivity(r, customIntent);
- ...
- }
- private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
- ...
- if (r.isPersistable()) {
- mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
- } else {
- mInstrumentation.callActivityOnCreate(activity, r.state);
- }
- ...
- }
对应着 LAUNCH_ACTIVITY, 调用到了 handleLaunchActivity 函数 -> performLaunchActivity 函数, 在 performLaunchActivity 函数中, 我们可以看到 mInstrumentation.callActivityOnCreate 的字样, 猜的没错的话, 这就是调用 Activity 的 onCreate 函数的入口了, 我们看下源码:
- Instrumentation.class
- /**
- * Perform calling of an activity's {@link Activity#onCreate}
- * method. The default implementation simply calls through to that method.
- * @param activity The activity being created.
- * @param icicle The previously frozen state (or null) to pass through to
- * @param persistentState The previously persisted state (or null)
- */
- public void callActivityOnCreate(Activity activity, Bundle icicle,
- PersistableBundle persistentState) {
- prePerformCreate(activity);
- activity.performCreate(icicle, persistentState);
- postPerformCreate(activity);
- }
- Activity.class
- final void performCreate(Bundle icicle) {
- performCreate(icicle, null);
- }
- final void performCreate(Bundle icicle, PersistableBundle persistentState) {
- ...
- if (persistentState != null) {
- onCreate(icicle, persistentState);
- } else {
- onCreate(icicle);
- }
- ...
- }
- public void onCreate(@Nullable Bundle savedInstanceState,
- @Nullable PersistableBundle persistentState) {
- onCreate(savedInstanceState);
- }
总结一下调用关系, Instrumentation. callActivityOnCreate-> Activity. performCreate->Activity.onCreate.
到此为止, 我们的整个 App 已经成功启动啦~
总结一下:
App 启动到调用 Activity.create 函数调用总结. PNG
2.Activity 调用 setContentView 做了什么?
敬请期待
来源: http://www.jianshu.com/p/45231992196f