Android之View的诞生之谜
来源:互联网 发布:伦敦公共交通网络 编辑:程序博客网 时间:2024/05/01 13:50
作者博客
http://www.cherylgood.cn
前言
hello,大家好,平时大家都说自定义view,这次给大家带来有关view的相关知识,希望你喜欢!
作为一名正在岗位上的Android开发者,工作中常常需要我们使用自定义View去实现一些天马行空的效果,而作为一名正在寻找工作的Android开发者而言,面试过程中自定义View的相关知识点也是热门的面试题目之一哦,好东西我们怎么能错过呢;
作为Android开发者,我们应该不断的丰富自身的知识体系结构,加强Android开发内功的修炼(个人看法:学习Android内部底层一些的知识,可视为内功。而对于api的灵活使用,可视为招式)。
本次我们将来探索自定义View的内功心法之自定义View的死亡三部曲:测量、布局、绘制。
在了解死亡三部曲之前,我们先从上层的视角看下死亡三部曲的执行流程。
Activity的布局文件是如何被加载的?
我们的activity中的视图是什么时候被加载的呢?setContentView(R.layout.main);这个方法你肯定会很眼熟:其实我们的activity就是通过这个方法加载我们的布局文件进行视图的渲染。那么我们就从他入手吧。
我们进入setContentView(R.layout.main)的源码看一下,注意代码中的注视:
window是什么东东?window是一个抽象类,他只有一个实现类,那就是phoneWindow,phoneWindow是android系统中窗口的顶级类。
我们接着看 getWindow().setContentView(layoutResID);
在渲染我们的布局文件前,先调用了installDecor()来初始化mContentParent,之前也说mContentParent是负责加载我们页面内容的容器,到底是不是呢?我们看下installDecor源码便知道了:
从2处我们看到mContentParent被创建,那么它是如何被创建的呢,他真的是如我们前面所说负责加载内容部分的父容器么?我们来一探究竟,我们看 mContentParent = generateLayout(mDecor)的源码:
小小的发现:从上面的代码我们可以解释很多开发中的技巧,看下面的代码,在加载我们的资源文件前,他就检查了FEATURE_ACTION_BAR和FEATURE_NO_TITLE属性,所以我们想让activity全屏或者没有actionBar的话,必须在setContentView调用之前设置。
接下来我们回到前面
setContentViewgetWindow().setContentView(layoutResID);方法,继续看mLayoutInflater.inflate(layoutResID, mContentParent); 这个方法 mContenParent我们已经知道是什么了,然后通过mLayoutInflater.inflate,我们的布局就被渲染出来了。
DecorView补充: DecorView是整个ViewTree的最顶层View,我们之前分析过她是是个FrameLayout布局,代表了整个应用的界面。在该布局下面,有标题view和内容view这两个子元素,而内容view则是上面提到的mContentParent。如下图:
到目前为止,通过setContentView实例化了DecorView并且加载了设置进来的布局文件。然后,并没有发现任何与测量、布局、绘制相关的点,可能你会想,我们不会搞错了吧,其实没有哦,你们想想,setContentView实在,既然还是不可见的,那我为什么要耗费资源去测量呢,你最终能不能露个脸还说不准呢。亏本的买卖咱不干。其实要想知道什么时候开始执行测量等工作,我们可以看下ActivityThread的源码,ActivityThread是android用来管理activity的,这家伙知道的肯定多一些。那么我们就来了解下ActivityThread的执行流程。
首先ActivityThread通过调用handleLaunchActivity启动我们的目标activity
也就是说在performLaunchActivity调用之后,activity的onCreate被调用,我们的资源文件不加载,但是此时还是不可见的,也就还没有进行侧脸之类的事情。
然后我们继续看ActivityThread.handleResumeActivity的源码:
知识补充:
Window是一个抽象的概念,一个Window对应一个View和一个ViewRootImpl;
Window和View是通过ViewRootImpl联系起来的。
ViewRootImpl才是一个View真正实现的动作。
WindowManager中也有一个WindowManagerImpl作为实现的类,负责具体的操作。
跟到这里,我们来总结一下,activity启动过程中,在执行handleResumeActivity时将我们的顶层视图DecorView通过WindowManager挂载到window中。
而WindowManager是个接口类,那么我们看看其实类对象WindowManagerImpl.addView方法
mGlobal其实是WindowManagerGlobal的一个内部实例,接着看WindowManagerGlobal.addView的源码:
我们继续看ViewRootImpl.setView方法的源码
setView完成的工作很多,如声明输入事件的管道,DisplayManager的注册,view的绘画,window的添加等等
作为绘制view的入口,我们来看下requestLayout方法
ViewRootImpl.scheduleTraversals()调用后,系统会发起一个异步消息,然后在异步消息执行过程中调用performTraversals()完成具体的View树遍历;
小子,总算是找到你了,我们来看下胜利的果实吧!
总结
通过上面内容,我们学到了一些小技巧,如移除状态栏的一些步骤,之前我们可能知道,嗯,是的,要在setContentView前调用requestFeature才可以,通过这次分析,我们之前可能是知道要这样子做才行,现在我们知道了为什么要这样子做。是不是写起代码来更踏实了呢?
通过这次分析,我们对于activity的创建流程也略知一二,希望对你有帮助
测量、布局、绘制的工作我们放到下一章节进行学习
- Android之View的诞生之谜
- android自定义View之钟表诞生记
- Android好奇之旅 环境搭建及Helloworld的诞生
- Android自定义View 之 View的测量
- Android 自定义View之View的绘制
- android之view的TouchDelegate
- Android之View的测量
- Android之View布局
- android之view
- Android 之 View ViewGroup
- Android之自定义View
- Android 之自制View
- android之View绘制
- Android View之测量
- android 之自定义View
- android 之View 一
- android基础之view
- android之View坐标系
- 数据类型转换——QQ号码验证
- quartz
- Flume架构以及应用介绍
- 【Android graphics】(一) Android SVG使用之AnimatedVectorDrawable
- 打击罪犯
- Android之View的诞生之谜
- 华为ENSP 模拟器 filezilla client 相互传文件 系统升级
- 大数据量下高并发同步的讲解(不看,保证你后悔)
- MVP+多线程+断点续传 实现app在线升级库 (手把手教你打造自己的lib)
- 拜占庭将军问题的探讨
- Android 把手机应用移植到PAD
- 网络直播间装修业的崛起
- 通达OA 小飞鱼是如何避免一次不必要的二次开发(图文)
- Syntax error, insert "}" to complete Block