Android 深入理解 View 的绘制流程和机制

 

 

1).Android 深入理解 View 的绘制流程和机制

http://blog.csdn.net/whb20081815/article/details/62236641

2). 

Android快速理解Activity、View及Window&WindowManager之间关系

 

http://blog.csdn.net/whb20081815/article/details/62419059

3).Android 动画用法+原理(Property Animation) 酷炫 UI动画

http://blog.csdn.net/whb20081815/article/details/64501074

4).Android 性能优化<七>自定义view绘制优化

 

http://blog.csdn.net/whb20081815/article/details/744747

 

 

 

同样是程序员差距咋就这么大呢?哭

ViewRoot:看源码直接搜索不到,需到源码网站看

View系统的绘制流程会从ViewRoot的performTraversals()方法中开始,performTraversals()的意思是:执行遍历

 

View的整个绘制流程可以分为以下三个阶段:

  • measure: 判断是否需要重新计算View的大小,需要的话则计算;
  • layout: 判断是否需要重新计算View的位置,需要的话则计算;
  • draw: 判断是否需要重新绘制View,需要的话则重绘制。
  • measure()、layout()、draw(),其内部又分别包含了onMeasure()、onLayout()、onDraw()三个子方法。
    这三个子阶段可以用下图来描述:

 

 

 

 

Android系统的视图结构的设计也采用了组合模式

 

 

 

 

总结:从以上分析可以看出View树的绘制是一个递归的过程,从ViewGroup一直向下遍历,直到所有的子view都完成绘制,那这一切的源头在什么地方(是谁最发起measure、layout和draw的)?当然就是在View树的源头了——ViewRoot!,ViewRoot中包含了窗口的总容器DecorView,ViewRoot中的performTraversal()方法会依次调用decorView的measure、layout、draw方法,从而完成view树的绘制。

 

onAttachedToWindow () 和 onDetachedFromWindow () 

onAttachedToWindow是在第一次onDraw前调用的。也就是我们写的View在没有绘制出来时调用的,但只会调用一次。

onDetachedFromWindow:销毁资源(既销毁view)之后调用。

 

 

veiw状态的保持:onSaveInstanceState()方法

 

 

 

问题:invalidate()和postInvalidate()的使用与区别

  Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:

Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 

  invalidate()是用来刷新View的,必须是在UI线程中进行工作。比如在修改某个view的显示时,调用invalidate()才能

看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。

  Android 程序默认情况下也只有一个进程,但一个进程下却可以有许多个线程。在这么多线程当中,把主要是负责控

制UI界面的显示、更新和控件交互的线程称为UI线程,由于onCreate()方法是由UI线程执行的,所以也可以把UI线程理解

为主线程。其余的线程可以理解为工作者线程。invalidate()得在UI线程中被调动,在工作者线程中可以通过Handler来通

知UI线程进行界面更新。而postInvalidate()在工作者线程中被调用。

 

 

问题二:

 

Android View刷新机制

        由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树,值得注意的是每次发起绘图时,并不会重新绘制每个View树的视图,而只会重新绘制那些“需要重绘”的视图,View类内部变量包含了一个标志位DRAWN,当该视图需要重绘时,就会为该View添加该标志位。

        调用流程 : 

        mView.draw()开始绘制,draw()方法实现的功能如下:

        绘制该View的背景

        为显示渐变框做一些准备操作(见5,大多数情况下,不需要改渐变框)          

        调用onDraw()方法绘制视图本身   (每个View都需要重载该方法,ViewGroup不需要实现该方法)

        调用dispatchDraw ()方法绘制子视图(如果该View类型不为ViewGroup,即不包含子视图,不需要重载该方法)值得说明的是,ViewGroup类已经为我们重写了dispatchDraw ()的功能实现,应用程序一般不需要重写该方法,但可以重载父类函数实现具体的功能。

 

Android的布局体系中,父View负责刷新、布局显示子View;而当子View需要刷新时,则是通知父View来完成。这种处理逻辑在View的代码中明确的表现出来:

子View调用invalidate时,首先找到自己父View(View的成员变量mParent记录自己的父View),然后将AttachInfo中保存的信息告诉父View刷新自己。

 

 

 

总结回答:

measure()方法,layout(),draw()三个方法主要存放了一些标识符,来判断每个View是否需要再重新测量,布局或者绘制,主要的绘制过程还是在onMeasure,onLayout,onDraw这个三个方法中

1.onMesarue() 为整个View树计算实际的大小,即设置实际的高(对应属性:mMeasuredHeight)和宽(对应属性: mMeasureWidth),每个View的控件的实际宽高都是由父视图和本身视图决定的。

2.onLayout() 为将整个根据子视图的大小以及布局参数将View树放到合适的位置上。

3.onDraw() 开始绘制图像,绘制的流程如下

 

首先绘制该View的背景 
调用onDraw()方法绘制视图本身 (每个View都需要重载该方法,ViewGroup不需要实现该方法) 
如果该View是ViewGroup,调用dispatchDraw ()方法绘制子视图

 

 

 

参考博客:

http://mp.weixin.qq.com/s?__biz=MzI0MjE3OTYwMg==&mid=401462221&idx=1&sn=dda1f3500c993d643dcdae6dd2cc3d6f&scene=21#wechat_redirect

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值