android高级UI之UI绘制流程(整体启动流程)
对于Android UI的学习在之前也针对性的进行过一些博客记录,但是还是没能系统全面的进行深入,有些零散,而在Android应用开发中它又是非常之重要的“硬”技能,所以接下来重新定下目标,要对它进行全面系统深入的再学习总结之路,目标是不管是对于面试还是实际工作中只要是涉及到UI效果这块都能做到心中有数,来对这块的硬技能的护城河加固再加固,对于新目标的开篇少了不要对UI绘制流程有一个整体的了解,这里是参考https://www.jianshu.com/p/0f6b4bc86c7b这位大神的简书为向导进行学习,拿来不可耻,但是重点是要利用网络上的各种好资源为自己所用,形成自己的知识体系。费话不多说,全面开启UI的系统学习。
先来引用博主开篇所说:
思路很清晰,所以接下来就来搞清楚这三个疑问则为这篇博文的全部内容。
分析前提示:
这次分析源码最好有以下基础:
1、Handler机制,之前总结过一篇:https://www.cnblogs.com/webor2006/p/11630538.html
2、Binder机制,之前总结过二篇:https://www.cnblogs.com/webor2006/p/11741743.html、https://www.cnblogs.com/webor2006/p/11811650.html
1.Android程序是如何启动,Activity生命周期如何调用?
对于APP启动时都会知道它会调用ActivityThread.main()方法,在之前的Android Framework层源码的分析中也多次看到了,下面还是从它分析起:
此时则会调用到这个类的attach()方法,查看里面的核心代码:
此时咱们看一下ActivityManager.getService()的细节:
关于Binder机制这块就不多说了,很明显可以看到ActivityManager是由系统服务所调用管理,并且通过在binder接口当中进行调用,这也是为什么我们讲Activity是跨进程访问的原因。下面咱们来看一下IActivityManager这个AIDL中的asInterface()的具体细节。发现在Android Studio中打不开打,这里引用博主的图:
此时再回到主流上来继续往下分析:
其中mAppThread为:
此时来看一下它的细节:
还是看不到它的源码,这里继续引用博主的:
然后大致纵览一下ApplicationThread中的方法,里面有很多schedule开头的方法:
貌似跟咱们的Activity的生命周期有关系,其中有一个跟启动Activity相关的方法:
其中在发送Handler消息时生成了一个ActivityClientRecord,这其实就是我们的Activity,好,接下来得处理这个LAUNCH_ACTIVITY消息了,如下:
也就是说咱们的Activity是由ApplicationThread来通过Handler来进行启动的,下面则来看一下这个handleLaunchActivity()的具体启动细节:
好,再来看一下这个方法的细节:
然后再调用了Activity的attach方法:
然后再往下看,则会看到调用Activity.onCreate()的身影:
好,到目前咱们对于Application到Activity的启动流程已经有了一个整体的了解,接下来则需要将焦点关注在setContentView()是如何将我们的布局xml文件加载进来的了。
2.在Activity.onCreate()当中我们的setContentView是如何将UI文件加载?
咱们直接从入口开始分析:
其中这个getWindow()则是咱们都熟知的PhoneWindow,所以直接定位到PhoneWindow.setContentView(),看一下核心代码:
这里再一下installDecor()的细节:
其中对于mDecor和mContentParent的定义:
好,下面来瞅一下生成的细节:
没啥,直接new了一个DecorView,好再来看另一个生成细节:
好,继续往下则可以看到貌似开始再选择xml布局文件了:
而关于Activity、Window、PhoneWindow、DecorView、View之间的关系如博主描述的:
总结一下installDector()这个方法它其实实际上是在初始化两个视图容器,然后加载系统的R资源及特征,产生了一个基本布局。
好再回到主流程继续往下分析,也就是这块:
具体它的解析细节看一下流程图:
具体解析细节这里就不看了,重点是对整个的UI绘制流程有一个了解。至此对于我们的xml布局文件是怎么加载的流程就清楚了,接下来则得看一下这些布局加载进来之后是如何呈现到手机上的。
3.UI是如何绘制的?
那绘制流程从哪分析起呢?很显然是从Activity.onResume()这块分析起,而起点当然还是在ActivityThread的那个H中了:
其中它里面会将咱们的view添加到WindowManager中,如下:
此时查看一下这个addView的细节:
其中WindowManager接口就继承了这个接口,而它的具体实现是WindowManagerImpl,所以:
其中mGlobal为:
它的核心实现为:
其中mView、mRoots、mParams三个成员变量为:
mViews保存的是View对象,DecorView
mRoots保存和顶层View关联的ViewRootImpl对象
mParams保存的是创建顶层View的layout参数。
而WindowManagerGlobal类也负责和WMS通信。
好,回到主流程继续:
跟进去看一下它的核心代码:
也就是说将ViewRoot作为了View的Parent,好,注意了,绘制的核心流程就要到了,此时需要回到setContentView的代码来了:
其实setLayoutParams它里面就涉及到绘制流程的代码了:
好,再来看一下它里面的细节:
而mParent在之前已经分析过了,叫ViewRootImpl,所以转到它里面来看一下:
这里就正式进入UI绘制的流程了,所以接下来再来看一下它的细节:
跟进去:
关于这个View的测量细节下一次再来分析,目前先只把整个绘制流程给搞通,好,回到主流程继续分析:
接着再进行布局了,关于具体布局的系统实现细节这里也不分析了,待之后再进行,还是往下分析主流程,不然很容易绕晕了:
对于上面绘制的大概流程用图再来回顾一下:
至此,对于整个绘制的完整核心流程就分析完了,不过对于具体View的测量、布局、绘制的流程这里还没开始分析,待下次再继续。