在Android的布局体系中,父View负责刷新、布局显示子View;而当子View需要刷新时,则是通知父View来完成。 步骤就是: 1、调用子View的invalidate() 2、跳转到上一层的invalidateChild函数中区 3、在一次调用invalidateChildInParent的函数一次层层刷新 4、具体的刷新后续操作,我就不清楚了,调用invalidate最终在代码上就在invalidateChild终止了的,所以表示有点点不清晰,求各位大牛介绍一下吧。。。。。?在此谢过了。。 让我来阅读源代码: 首先在View类中: /** * Invalidate the whole view. If the view is visible, {@link #onDraw} will * be called at some point in the future. This must be called from a * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}. */ public void invalidate() { if (ViewDebug.TRACE_HIERARCHY) { ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE); } if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) { mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID; final ViewParent p = mParent; //获得父类View的对象 final AttachInfo ai = mAttachInfo;//获得匹配 if (p != null && ai != null) { final Rect r = ai.mTmpInvalRect; r.set(0, 0, mRight - mLeft, mBottom - mTop);//设置本View的尺寸,其实就是大小没有设置位置 // Don't call invalidate -- we don't want to internally scroll // our own bounds p.invalidateChild(this, r); //调用父类的刷新函数 } } } 本篇文章来源于 Linux公社网站(www.) 原文链接:http://www./Linux/2012-07/65023.htm 在Android的布局体系中,父View负责刷新、布局显示子View;而当子View需要刷新时,则是通知父View来完成。这种处理逻辑在View的代码中明确的表现出来:
public void invalidate() { // 设置刷新区域为自己的尺寸
子View调用invalidate时,首先找到自己父View(View的成员变量mParent记录自己的父View),然后将AttachInfo中保存的信息告诉父View刷新自己。
View的父子关系的建立分为两种情况: 1) View加入ViewGroup中 private void addViewInner(View child, int index, LayoutParams params, boolean preventRequestLayout) { ..... // tell our children ..... }
2)DecorView注册给WindowManagerImpl时,产生一个ViewRoot作为其父View。 public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView){ ..... view.assignParent(this); .... }
AttachInfo是在View第一次attach到Window时,ViewRoot传给自己的子View的。这个AttachInfo之后,会顺着布局体系一直传递到最底层的View。 View.java void dispatchAttachedToWindow(AttachInfo info, int visibility) { .....
ViewGroup.java void dispatchAttachedToWindow(AttachInfo info, int visibility) {
并且在新的View被加入ViewGroup时,也会将该AttachInfo传给加入的View ViewGroup.java private void addViewInner(View child, int index, LayoutParams params, boolean preventRequestLayout) { child.dispatchAttachedToWindow(mAttachInfo, (mViewFlags&VISIBILITY_MASK)); }
到这里明白了mParent与AttachInfo代表的意义,可以继续刷新过程的分析。
在invalidate中,调用父View的invalidateChild,这是一个从第向上回溯的过程,每一层的父View都将自己的显示区域与传入的刷新Rect做交集。
public final void invalidateChild(View child, final Rect dirty) { // 需要刷新的子View的位置 // Mark the child as dirty, using the appropriate flag
public ViewParent invalidateChildInParent(final int[] location, final Rect
dirty) { // 根据父View的位置,偏移刷新区域 //计算实际可刷新区域
这个向上回溯的过程直到ViewRoot那里结束,由ViewRoot对这个最终的刷新区域做刷新。 ViewRoot.java public void invalidateChild(View child, Rect dirty) { scheduleTraversals(); } http://blog.csdn.net/dragondog/article/details/6454551 |
|
来自: 昵称11494597 > 《android、java》