关于view的显示和绘制,不会去了解底层,仅仅在framework层做一些概述:以oo的思想,那么窗口的显示,内容的显示一定都有对应的类来相对应。了解了这一点之后,就去抽象一下android为了显示窗口而做的封装。

首先来说每一个activity一定有一个可供显示图像的东西,window,就是他抽象为一个window可以挂载所有view。在android中有一个实现类就是phonewindow,他实现了window的所有功能。那么可供挂载的view一定有一个根类,是decorview,这个是一个phonewindow的内部类。字面意义来看就是一个装饰类。他也仅仅就是一个view类,但是确实所有view类的根节点。然后我们使用xml布局的类或者是代码创建的类就可以挂载到这个view上了,还有一个东西叫viewroot,好像这个类才是根一样?这完全就是两个东西,viewroot其实是在windowmanager中!windowmanager又是他妈什么?这个和之前的activityThread和Instramentation的关系有些类似。window主要就是描述了window的所有功能,主要和我们的界面交互。windowManager是继承于viewmanager,主要就是操作view的添加view,删除view。viewroot是在windowmanager中,是为了和phonewindow交互,可以看一下继承体系,是继承与Handler也就说是主要处理消息的,viewroot处理的消息就是屏幕和键盘等等的一切交互动作。在UI线程进入消息循环之后,我们的交互就只是能通过外界的中断,而这些东西都由底层交给viewroot。然后在控制phonewindow,分发消息。进行界面view的各种显示和处理。

tip:上面的过程有点乱,简单来说我们可以代码操作的就是activity,activity里面有window对象,window对象负责的就是界面,window里面有一个windowManager和decorview。windowamanger负责在的decorview上添加view。也就是说window里面是没有addview方法的,只有利用windowmanager才可以添加或操作view。可以做一个实验,在oncreate中getWindowManager().removeView(getWindow().getDecorView());就是把decorview从window上删除,这个就是一个黑色背景,并且无法交互一会就会anr。这就说明decorview就是view的根。

说完代码操作的方式,就可以看一下底层对应的实际对象,window和windowmanager都是抽象类,decorview也使用的view的类型,在底层实际上是phonewindow ,windowmanagerimpl,decorview。然后这个些都只是view视图的显示,我们要交互使用viewroot。viewroot会和android系统的服务进程windowManagerService交互。进行把界面的各种消息添加到MessageQueue。viewroot就是一个Handler。

这个就是类层面的结构,可以看到抽象的都很好,使用oo思想,先来抽象每一个层面的对象,然后利用view和数据分离。window管理数据,windowManager处理view。

来看一下源码的调用流程:之前的创建activity的时候就使用了attach函数来把activity和Context挂在在了一起。这时候可以看到attach函数中做了什么?他创建了window对象,也就是phonewindow,他使用了polocyManager.makenewwindow,来创建了一个phonewindow,然后setWindowManager创建l了WindowManager。这个wm虽然看起来是LocalWIndowManager其实都是简单的类型包装,实际的就是windowManagerImpl。之后就是setcontentview中去添加了view,然后在onresume后调用activity的makeVisiable使得view绘制出来。

tip:实际上这里有一个问题:就是在oncreate之前是attach函数添加了phonewindow对象,但是在这之后直到oncreate并没有显示phonewindow的代码,但是你注意观察的话就会发现,在oncreate之前实际上界面上就有了decorview的布局了(后面具体说)。为什么?这感觉不合理,也就是在onstart之后按理说才是界面显示器。我现在都有疑问(未解决)。个人感觉这个界面显示是指的我们的布局view被加到了decroview中,并不是指的界面动作。生命周期函数有诸多的和用户界面不一致,其实更合理的是代码运行和生命周期是一致的。回到问题,其实源代码中开启activity要从上一篇讲的activityStack的realstartActivityLocked中调用的,这个里面有一个windowManagerService调用了windowManger的setAppvisiablity。这我感觉就是我们程序的显示。之后才发消息给ActivityThread去显示activity。总之这个过程很复杂。了解这些过程有助于我们以后的开发,但是要彻底了解还有很长的路要走。

了解了上面之后,研究的主线就清楚了,1,view如何添加到decorview? 2view 是如何绘制的?

1.view的解析和添加:android中view有两种方法创建:代码和xml。一般来说代码创建的时候调用的是一个参数的构造函数,而xml布局要使用两个参数的构造,这是为什么?多出来的参数就是AttributeSet 也就是在xml中的熟悉级,他要利用这个来进行解析转化为本身的属性值。这一切的过程都是从setcontentview开始的,phonewindow调用自己的setcontentview。里面调用了installDecor来创建了decorview。

tip:这时候就要分析decorview到底是是什么了,decorview实际上里面有一个LinearLyout,第一个元素为titleBar,现在为actionBAr。然后第二个元素就是frameLayout,也就是我们的布局的父类布局。setcontentview就是把布局放到这个framelayout里面。所有的解析过程都在insatlldecor;里面。

生成了decroview之后就是为mContentParent(framelayout)设置内容了,也就是解析xml。一般使用解析都是使用LayoutInflate。有很多生成方式,使用Context的getsystemservice,或者调用static函数from,或者直接View.Inflate,其实都是一样的,有了LayoutInfalte就调用inflate来解析view布局。

tip:这个时候要了解几个技巧和概念:

1megre和include标签,include是为了布局复用的标签,这个很好了解,但是megre呢?实际是为了消除冗余的父类布局,也就是说当使用include引入一个布局之后,可能会出现两个父类布局重复,这个时候必然是冗余了,可以将include的父类布局换成megre,解析的时候自动就会无视megre,这个实际上是在代码xml期间的标签。

2.要注意的就是viewGroup,我们知道view是一个树结构,存的时候实际就是每一个viewgroup存储自己的孩子在一个数组中view[] mChildren,无论是便利还是添加都是通过这个数组的。

具体的解析过程在inflate里面,inflate是解析根布局标签,然后交给rinflate去循环解析子类的标签,解析之后又createViewFromTag就是生成相应的对象,调用createView反射了对应类,并且调用了构造函数,这里就是使用的两个参数的构造,arg0是Context,arg1是attr就是xml属性集合。然后根据生成的view添加到viewgoup中,最后添加到decroview中。到此为止,view的解析就完成了。

2view如何绘制?

要找到这个过程实际上要到viewroot中去寻找,几乎所有的和窗口的动作都是由系统服务windowMangerService来执行的,而和他交互的就是viewroot,viewroot里面管理了view的显示和事件等动作。当要显示布局的时候,activity的makeVisiable最终调用到了viewroot的scheduleTraversals,然后加到了消息队列中处理之后调用了perfromTraverals,英语就是遍历的意思,在这个函数中执行了view的3个绘制过程在300多行的代码过程中调用了measure,layout,draw这也就是为什么要将这3个过程称之为view绘制流程。

measure是测量,也就是测量出每一个view的大小,lyout就是布局,布局也就是要把每一个view位置明确了,draw就是绘制,也就是表现到视图上,其实就是在一个bitmap的画布上画出各个控件来。

具体的绘制在下一篇绘制中叙述,所以综上就是我们应该了解的view的概述,其中,我们抽象的思想和如何去在一个界面上展现view的思想应该是我们关注的,以及很多的源代码都要认真学习。以前一直觉的自己很熟悉android,现在看来真是讽刺,android系统了不起,以前真实太无知了。了解更多之后,你就更加的知道自己的渺小。

android view : 概述的更多相关文章

  1. [Learn Android Studio 汉化教程]第二章:Android Studio概述(一)

    [Learn Android Studio ]第二章:Android Studio概述(一) Android Studio是一个视窗化的开发环境.为了充分利用有限的屏幕空间,不让你束手束脚,Andro ...

  2. Android异常:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original

    Android异常:android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that cr ...

  3. Android View框架的measure机制

    概述 Android中View框架的工作机制中,主要有三个过程: 1.View树的測量(measure)Android View框架的measure机制 2.View树的布局(layout) Andr ...

  4. Android零基础入门第33节:Android事件处理概述

    原文:Android零基础入门第33节:Android事件处理概述 通过对Android基本组件的学习,也有接触少部分Android的事件处理,比如按钮的点击事件.选框的状态切换事件. 一.Andro ...

  5. Android View 的添加绘制流程 (二)

    概述 上一篇 Android DecorView 与 Activity 绑定原理分析 分析了在调用 setContentView 之后,DecorView 是如何与 activity 关联在一起的,最 ...

  6. Android View的事件分发机制探索

    概述 Android事件传递机制也是Android系统中比较重要的一块,事件类型有很多种,这里主要讨论TouchEvent的事件在framework层的传递处理机制.因为对于App开发人员来说,理解f ...

  7. Android View框架的draw机制

    概述 Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure) Android View框架的measure机制 2.View树的布局(layout)Andr ...

  8. Android View框架的layout机制

    概述 Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure) Android View框架的measure机制 2.View树的布局(layout)Andr ...

  9. 虾扯蛋:Android View动画 Animation不完全解析

    本文结合一些周知的概念和源码片段,对View动画的工作原理进行挖掘和分析.以下不是对源码一丝不苟的分析过程,只是以搞清楚Animation的执行过程.如何被周期性调用为目标粗略分析下相关方法的执行细节 ...

随机推荐

  1. sql索引实例

    1.创建表并插入数据 在Sql Server2008中创建测试数据库Test,接着创建数据库表并插入数据,sql代码如下: USE Test IF EXISTS (SELECT * FROM INFO ...

  2. Writing Text Files On The Client in Oracle Forms 10g

    Below is the example to write file on client in Oracle Forms 10g with webutil library package.Note:  ...

  3. winfrom的两种拖拽方式和界面阴影

    方式1private Point mouseOffset; //记录鼠标指针的坐标 private bool isMouseDown = false; //记录鼠标按键是否按下 private voi ...

  4. [Python正则表达式] 字符串中xml标签的匹配

    现在有一个需求,比如给定如下数据: 0-0-0 0:0:0 #### the 68th annual golden globe awards #### the king s speech earns ...

  5. IOS详解TableView——内置刷新,EGO,以及搜索显示控制器

    内置刷新 内置刷新是苹果IOS6以后才推出的一个API,主要是针对TableViewController增加了一个属性,refreshControl,所以如果想用这个内置下拉刷新的话,最好给你的Tab ...

  6. JAVA 使用POI导出数据格式为Execl

    需要下载一个poi的jar包. 控制器 @Override public void getContractListExecl(Contract contract, BindingResult resu ...

  7. Android Gradle的使用

    说明: 在Android Studio中的Terminal可以直接使用Gradle命令行,不需要配置环境,而想直接在电脑的命令行使用Gradle命令行, 则需要配置环境,Window下配置Gradle ...

  8. Linux 下 git连接github的使用

    1.安装git sudo apt-get install git 2.创建github帐号 3.Linux创建SSH密钥: ssh-keygen  //一直默认 4.将公钥加入到Github账户信息A ...

  9. 深入理解 AngularJS 的 Scope

    JavaScript 的原型继承就是奇葩. 之前在 V2EX 上看到讨论说,不会 OOP 的 JavaScript 的程序员就是野生程序员.看来我是属于野生的.   一.遇到的问题 问题发生在使用 A ...

  10. WEB UI 整理

    当下对于网站前段开发人员来说,很少有人不使用一些JS框架或者WEB UI库,因此这些可以有效提高网站前段开发速度,并且能够统一开发环境,对于不同浏览器的兼容性也不需要程序员操心,有了这些优点,当然大家 ...