App 启动过程(含 Activity 启动过程) | 安卓 offer 收割基

本文作者: 布兰柯基

本文链接: 

https://blankj.com/2018/12/18/android-adapt-screen-killer/


618,祝大家购物愉快,文末有彩蛋~~


这道题在曾经面试「菜鸟网络」中遇到过,不过当时只问了「Activity 启动过程」,这里对整个「App 启动过程」进行完整的源码分析,希望可以帮助到大家。

源码分析

1. Launcher 捕获点击事件,其过程为 Launcher#onClick -> Launcher#onClickAppShortcut -> Launcher#startAppShortcutOrInfoActivity -> Launcher#startActivitySafely -> Activity#startActivity,其 Launcher3 相关源码如下所示:

2. 以 API 27 源码为例,说到了 Acitvity#startActivity,我们点击源码可以发现调用的是 Activity#startActivityForResult,其中调用到了 Instrumentation#execStartActivity 这个方法,源码如下所示:

3. 在 Instrumentation#execStartActivity 中我们可以发现它调用了 ActivityManager#getService()#startActivity,其 ActivityManager#getService() 是采用单例,返回的是实现 IActivityManager 类型的 Binder 对象,它的具体实现是在 ActivityManagerService 中。

4. 我们再到 ActivityManagerService#startActivity 查看其源码,发现其调用了 ActivityManagerService#startActivityAsUser,该方法又调用了 ActivityStarter#startActivityMayWait,源码如下所示:

5. 我们查找到 ActivityStarter#startActivityMayWait,其间调用了 ActivityStarter#startActivityLocked,接着是 ActivityStarter#startActivity,然后是 ActivityStarter#startActivityUnchecked,其调用了 ActivityStackSupervisor#resumeFocusedStackTopActivityLocked,源码如下所示:

6. 到 ActivityStackSupervisor#resumeFocusedStackTopActivityLocked 中查看发现其调用了 ActivityStack#resumeTopActivityUncheckedLocked,然后是 ActivityStack#resumeTopActivityInnerLocked,接着变又回到 ActivityStackSupervisor.java,调用了 ActivityStackSupervisor#startSpecificActivityLocked,这个方法中会判断要启动 App 的进程是否存在,存在则通知进程启动 Activity,否则就先将进程创建出来,其源码如下所示:

7. 我们分析进程尚未存在的情况,因为我们后续还会再次遇到 ActivityStackSupervisor#realStartActivityLockedActivityStackSupervisor#startSpecificActivityLocked 中创建进程使用到的 mService 为 ActivityManagerService,我们查看 ActivityManagerService#startProcessLocked 的源码如下所示:

8. 发现最终调用的事 Process#start 来启动进程,进程的入口就是在 android.app.ActivityThread.java 类中的 main() 函数,因此接下来我们从 ActivityThread#main 来分析,其调用了 ActivityThread#attach,其中 ActivityManager.getService() 之前提到过,返回的是一个是实现 IActivityManager 类型的 Binder 对象,它的具体实现是在 ActivityManagerService 中,相关源码如下所示:

9. 我们又回到了 ActivityManagerService 中,查看其 attachApplication 函数,发现调用了 thread#bindApplication 和 mStackSupervisor#attachApplicationLocked 我们依次讲解这两个方法要做的事情,源码如下所示:

10. 上面说到的thread#bindApplication 中的这个 thread 是来自于 ActivityThread#mAppThread,其类型是 ApplicationThread,是 ActivityThread 的一个内部类,继承自 IApplicationThread.Stub,我们来查看 ApplicationThread#bindApplication,发现最后调用了 ActivityThread#sendMessage 方法,它内部调用了 mH.sendMessage 来发送消息,mH 是 ActivityThread 的内部类 H 的一个实例,查看 H#handleMessage 来查看它是怎么处理发送过来的消息,其最终走到了 ActivityThread#handleBindApplication

在源码中我们可以发现它先创建 mInstrumentation 对象,调用 data#info#makeApplication 来创建 Application 对象,其对象 data#info 为 LoadedApk 的一个实例,查看 LoadedApk#makeApplication 中代码可以发现,其调用了 Instrumentation#newApplication 方法,内部靠 Class#newInstance() 完成对 Application 实例化,然后调用 Application#attach(context) 来绑定 Context

以上创建完 Application 对象后便是调用 Instrumentation#callApplicationOnCreate 走 Application 的 onCreate 生命周期,以上涉及到的全部源码如下所示:

11. 说完了 9 中的 thread#bindApplication,下面我们继续说 mStackSupervisor#attachApplicationLocked,其 mStackSupervisor 是 ActivityStackSupervisor 的一个实例,我们查看 ActivityStackSupervisor#attachApplicationLocked 方法中发现会调用 ActivityStackSupervisor#realStartActivityLocked,其方法会调用 app#thread#scheduleLaunchActivity,源码如下所示:

12. 上面说到的 app#thread#scheduleLaunchActivity 中的 thread 是前面提到过的 IApplicationThread,它的实现类是 ActivityThread#ApplicationThread ,我们查看 ActivityThread#ApplicationThread#scheduleLaunchActivity 中的代码发现最终是发送 LAUNCH_ACTIVITY 消息,这步我们在第 10 步中有过分析,我们直接查看其处理消息相关代码即可,在 H#handleMessage 中,我们可以看到其会接收并处理很多和四大组件相关的操作,我们查看对 LAUNCH_ACTIVITY 的处理,发现对其处理的方法是 ActivityThread#handleLaunchActivity,它调用到了 ActivityThread#performLaunchActivity 方法,其中的实现再次涉及到了 Instrumentation类,之前是在创建 Application 对象用到了它,如今是创建 Activity 对象又用到了它,其 Instrumentation#newActivity 也是通过 Class.newInstance() 来实例化 Activity,实例化结束后回到 ActivityThread#performLaunchActivity 中来让 activity 依附到 window 中,然后callActivityOnCreate 走 Activity 的 onCreate 生命周期,涉及到的源码如下所示:

到此为止,一个 App 的启动过程已分析结束,最后献上启动涉及到的类的流程图:

640?wx_fmt=jpeg结语


我正在打造一个帮助 Android 开发者们拿到更好 offer 的面试库————安卓 offer 收割基,欢迎 star,觉得不错的可以持续关注,有兴趣的可以一起加入进来和我一同打造。

https://github.com/Blankj/AndroidOfferKiller


推荐阅读

Android 屏幕适配终结者

Android 自定义时钟控件 时针、分针、秒针的绘制这一篇就够了

微信扫一扫识别小程序


640?wx_fmt=png长按识别小程序,参与抽奖

640?wx_fmt=png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值