-
创建Context,具体实现为ContextImpl
-
附加上下文,不仅仅包括context,还包括所有跟Activity运行有关的重要的系统变量
-
最后执行生命周期回调
总结:
-
首先应用向AMS发起startActivity请求,
-
如果应用没有启动,AMS会向Zygote发起启动进程请求
-
zygote收到请求之后就会启动应用进程
-
应用进程启动之后,就会向AMS发起attchApplication的IPC调用,主要使用与注册Application Thread
-
接下来AMS会向应用发起bindApplication IPC调用,用来给应用初始化Application
-
之后AMS又向应用发起scheduleLaunchActivity IPC调用,这个调用就是给应用创建和加载Activity并且执行Activity生命周期
2. Activity显示原理
相关问题
-
Activity的显示原理(Window/DecorView/ViewRoot)
-
Activity的U刷新机制(Vsync/Choreographer)
-
U|的绘制原理(Measure/Layout/Draw)
-
Surface原理(Surface/SurfaceFlinger)
答题要点
-
PhoneWindow是什么,怎么创建的?
-
setContentView原理是什么?
-
Activity在onResume之后才会显示的原因是什么?
-
ViewRoot是干嘛的,是View Tree的rootView么?
-
View的显示原理是什么?WMS发挥了什么作用?
总结
代码细节如图32
-
Activity启动时会创建一个PhoneWindow
-
phoneWindow里有一个DecorView,DecorView是整个Activity的View Tree的Root view
-
ContentView是DecorView的一部分
-
Decorview会对应一个ViewRootImpl对象,ViewRootImpl对象可以与WMS双向通信
-
ViewRootImpl可以通过IwindowSession向WMS发起binder调用
-
WMS通过IWindow向应用端发起binder调用
-
Activity之所以能显示出来,最重要的一步就是ViewRootImpl的创建,并由ViewRootImpl全权负责Decorview的绘制
-
ViewRootImpl会在WMS里注册一个窗口,WMS会统一管理所有窗口的大小,位置以及层级,在第一次绘制的时候,ViewRootImpl会向WMS申请一个Service用于绘制
-
绘制完成之后,SurfaceFlinger就会按照WMS中提供的Window层级、大小、位置来对surface进行合成,合成完毕之后就可以写到屏幕的帧缓冲区显示出来
-
如图33
3. 应用的UI线程是怎么启动的
答题要点
-
什么是UI线程?
-
UI线程也就是刷新UI所在的线程
-
UI是单线程刷新的(如果是多线程导出上锁容易导致问题)
-
UI线程的启动流程,消息循环是怎么创建的
-
了解Android的UI显示原理,UI线程和U|体系之间是怎么关联的?
Activity.runOnUiThread(Runnable)与view.post(Runnable)
-
Activity.runOnUiThread(Runnable)
-
结论1:对于Activity来说,UI线程就是主线程
-
图34
-
view.post(Runnable)
-
结论2:对View来说,它的U线程就是ViewRootlmpl创建的时候所在的线程!
-
图35
-
子线程刷新UI的问题
-
结论:只有创建了view树的线程,才能访问它的子view
-
如图36
-
结论3:Activity的DecorVie对应的ViewRootlmpl是在主线程创建的
-
如图37
关于UI线程的三个结论
-
对Activity来说,UI线程就是主线程
-
activity.runOnUiThread()
-
对View来说,UI线程就是ViewRootlmpl创建的时候所在的线程
-
View.post(Runnable r)
-
Activity的DecorView对应的ViewRootlmpl是在主线程创建的
-
checkThread
子线程刷新UI可以么?
可以,代码如下
new Thread(){
@Override
public void run(){
//因为添加window是IPC操作,回调回来时,需要handler切换线程,所以需要Looper
Looper.prepare();
…
getWindowManager().addView(view,params);
//开启looper,循环取消息。
Looper.loop()
}
}.start();
Looper.prepare()与Looper.prepareMainLooper()的区别
-
Looper.prepareMainLooper(),应用进程启动之后MainLooper就已经设置好了
-
prepare(false)表示looper不能退出,对于mainLooper来说looper是不能退出的,其他线程是可以退出的,调用主线程的looper.quit是会抛出异常的
总结
-
UI线程指的是刷新UI的线程,由于ViewRootImpl是在主线程中创建的,所以实际上指的就是主线程
-
UI线程的启动实际上就是主线程的启动,分三步
-
①Zygote fork进程
-
②启动binder线程
-
③ 执行入口函数 ActivityThread.main()
-
消息循环时通过主线程的Looper开启的
Service相关
1. 说说Service的启动原理
考察点
-
service启动有哪几种方式?
-
startService
-
bindService
-
区别:bindServcie不会触发onStartCommand
-
service启动过程中主要流程有哪些?
-
service启动过程涉及哪些参与者,通信过程是怎样的?
代码分析
主要的启动流程
-
如果Service启动了,直接调用onStartCommand
-
如果Service没有启动
-
进程启动了
-
启动Service
-
调用onStartCommand
-
进程没有启动
-
启动进程
-
启动Service
-
调用onStartCommand
启动过程涉及哪些参与者,以及通信过程
-
进程A要开启一个Service,向AMS发起了startService调用
-
如果AMS发现Service进程没有启动,就会通过socket向zygote进程发起启动进程的请求
-
zygote进程会启动应用进程
-
应用进程启动之后,就会执行ActivityThread main函数
-
在入口函数中向AMS发起attchApplication的binder调用,AMS就知道了应用进程已经就绪了
-
然后AMS会向应用发起bindApplication的binder调用,让应用创建自己的Application
-
接下来就开始处理这个应用进程里pending的一些应用组件,比如Service相关,这里连发了两条请求,这两个请求都是在主线程中执行的
-
scheduleCreateServices用于在应用端create Service
-
cheduleServiceArgs用于在应用端调用onStartCommand
-
如图41
总结
-
首先回答出启动方式,答案如上
-
然后回答出启动过程中的主要流程
-
最后回答出service启动过程涉及哪些参与者,通信过程是怎样的?
2.说说Service的绑定原理
考察点:
-
bindService用法
-
了解bindServcie的大致流程
-
bindService涉及哪些参与者,通信过程是怎样的?
用法: 图43
总体流程
-
首先应用向AMS发起bindService调用
-
AMS检查是否有binder句柄
-
如果有,就会将binder句柄回调给应用
-
如果没有,AMS就会向Service请求句柄,Service会将句柄发布到AMS,然后AMS会将binder句柄回调给应用
-
应用在拿到binder句柄之后,就可以向Service发起binder调用了
-
应用端bindService的时候会带一个IserviceConnection对象
-
这个对象是一个Bindder对象,把这个对象传到AMS之后,AMS就会将它保存起来
-
等到Service绑定成功了,AMS就会调用IserviceConnection的connected函数来主动通知应用端
-
然后IServiceConnection持有了ServiceConnection的引用,这意味着可以调用ServiceConnection的函数
-
值得注意的是,IServiceConnection和ServiceConnection不一定是一对一的关系
-
一个context和一个ServiceConnection构成一个二元组,这个二元组跟IserviceConnection是一对一的关系
-
这意味着同一个ServiceConnection用不同的Context去bind这个Service的时候,就会对应不同的IserviceConnection
-
同样,同一个Context用不同的ServiceConnection去bind这个Service的话,那么也会对应不同的IServiceConnection
-
对于AMS来说,他只认IServiceConnection,只要IServiceConnection不同,他就认为这是不同的Connection
bindService实现原理 bindService从应用端发到了AMS, 在AMS中处理函数就是bindServiceLocked
首先来看一组数据结构
-
应用端一个Service在AMS中对应一个ServiceRecord
-
一个ServiceRecord又可以包含一个或多个IntentBindRecord
最后
今天关于面试的分享就到这里,还是那句话,有些东西你不仅要懂,而且要能够很好地表达出来,能够让面试官认可你的理解,例如Handler机制,这个是面试必问之题。有些晦涩的点,或许它只活在面试当中,实际工作当中你压根不会用到它,但是你要知道它是什么东西。
最后在这里小编分享一份自己收录整理上述技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【算法合集】
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
droid核心高级技术PDF文档,BAT大厂面试真题解析】**
[外链图片转存中…(img-tyxADj82-1643536856874)]
【算法合集】
[外链图片转存中…(img-6Lq2SHVU-1643536856874)]
【延伸Android必备知识点】
[外链图片转存中…(img-weISAgiK-1643536856875)]
【Android部分高级架构视频学习资源】
Android精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!