本文讲解从开机到app显示画面的流程,但不分析源码,如果想阅读源码请到参考文章中查阅。
纸上说来终觉浅,建议有时间的小伙伴去我的B站观看视频讲解:Android进阶:手机开机到APP启动中间FrameWork层发生了什么?
本文把这段流程分为三部分:
从开机到显示应用列表从点击应用图标到Activity创建成功从Activity创建成功到显示画面先看流程图:
开机加电后,CPU先执行预设代码、加载ROM中的引导程序Bootloader和Linux内核到RAM内存中去,然后初始化各种软硬件环境、加载驱动程序、挂载根文件系统,执行init进程。
init进程会启动各种系统本地服务,如SM(ServiceManager)、MS(Media Server)、bootanim(开机动画)等,然后init进程会在解析init.rc文件后fork()出Zygoto进程。
Zygote会启动Java虚拟机,通过jni进入Zygote的java代码中,并创建socket实现IPC进程通讯,然后启动SS(SystemServer)进程。
SS进程负责启动和管理整个framework,包括AMS(ActivityManagerService)、WMS(WindowManagerService)、PMS(PowerManagerService)等服务、同时启动binder线程池,当SS进程将系统服务启动就绪以后,就会通知AMS启动Home。
AMS通过Intent隐式启动的方式启动Launcher,Launcher根据已安装应用解析对应的xml、通过findBiewById()获得一个RecycleView、加载应用图标、最后成功展示App列表。
Question 1: Zygote进程为什么使用Socket而不是Binder? fork不允许存在多线程,而Binder通讯恰巧就是多线程;
Question 2:什么是窗口? Android系统中的窗体是屏幕上的一块用于绘制各种UI元素并能够响应应用户输入的一个矩形区域,从原理上来讲,窗体的概念是独自占有一个Surface实例的显示区域,比如Dialog、Activity的界面、壁纸、状态栏以及Toast等都是窗体;
先看流程图:
//然后点击应用图标后,先检查要打卡的Activity是否存在 --> Launcher.startActivitySafely() --> Launcher.startActivity() --> Activity.startActivity() --> Activity.startActivityForResult() //然后获取AMS的代理AMP --> Instrumentation.execStartActivity() --> ActivityManagerNative.getDefault().startActivity() --> ActivityManagerProxy.startActivity() --> ActivityManagerService.startActivity() --> startActivityAsUser(intent, requestCode, userId) --> ActivityStackSupervisor.startActivityMayWait() --> ActivityStackSupervisor.resolveActivity() --> ActivityStackSupervisor.startActivityLocked() --> new ActivityRecord对象,获取ActivityStack --> 找到ActivityStack后Launcher.onPause() //准备启动进程 --> ActivityManagerService.startProcessLocked() //通过socket通知Zygote创建进程 --> zygoteSendArgsAndGetResult() //创建ActivityThread --> ActivityThread.main() //告诉AMS我已经创建好了 --> ActivityThread.attach() --> ActivityManagerProxy.attachApplication() --> ActivityMangerService.attachApplication() //找到Application实例并初始化 --> ActivityMangerService.attachApplicationLocked() --> ApplicationThread.bindApplication() //创建Application --> AcitvityThread.bindApplication() --> Application.oncreate() //启动Activity --> ActivityStackSupervisor.attachApplicationLocked() --> ActivityStackSupervisor.realStartActivityLocked() --> ActivityThread.scheduleLaunchActivity() //进入UI线程 --> handleLaunchActivity() --> performLaunchActivity() //创建Activity实例 --> Instrumentation.newActivity() --> Activity.onCreate()Question 1: 如何判断APP是否已经启动? AMS会保存一个ProcessRecord信息,有两部分构成,“uid + process”,每个应用工程序都有自己的uid,而process就是AndroidManifest.xml中Application的process属性,默认为package名。每次在新建新进程前的时候会先判断这个 ProcessRecord 是否已存在,如果已经存在就不会新建进程了,这就属于应用内打开 Activity 的过程了。
onCreate()方法中先执行setContentView()方法将对应的xml文件传入,之后会去调用window.setContentView(),最终会在这里创建Decorview并填充标题栏、状态栏,然后获取contentParent,然后调用LayoutInflater.inflate解析xml文件获取根root(ViewRootImpl),通过root.addView()将contentParent添加到ViewRootImpl中去,至此onCreate()结束。
开始onResume()阶段,在开始会向H类发送一个消息,然后在ActivityThread中获取之前创建的Decorview并调用windowManager.add(),最后在windowManager中将窗口和窗口的参数传到root.setView(),然后ViewRoot通过Binder调用WMS,使WMS所在的SS进程接收到按键事件时,可以回调到该root,同时ViewRoot会向自己的handler发送一条消息,然后进行处理(performTraversals),之后开始绘制过程(在Surface的canvas上绘制)。
先利用MeasureSpec完成onmeasure(),然后在onlayout()中确定各元素的坐标,ondraw()负责将view画到canvas上,再通过Surface进行跨进程最终调用Native层的SGL、openGI,最后再去调用硬件CPU进行渲染操作,最终界面显示在你眼前
作者:OldJii 链接:https://juejin.im/post/6844903943038992398
对文章有何见解,或者有何技术问题,都可以在评论区一起留言讨论,一定会回复的。 也欢迎大家来我的B站找我玩,各类Android架构师进阶技术难点的视频讲解,任君白嫖~ B站直通车:https://space.bilibili.com/484587989
喜欢文章的小伙伴别忘了点个关注,留个赞再走呀,一个专注Android面试的小喵喵~