流行网站开发框架,莆田有哪些网站建设公司,广州市专业网站设计,邯郸58同城网本文实例讲述了Android View刷新机制。分享给大家供大家参考#xff0c;具体如下#xff1a;一、总体说明在Android的布局体系中#xff0c;父View负责刷新、布局显示子View#xff1b;而当子View需要刷新时#xff0c;则是通知父View来完成。二、代码分析1).ViewGroup的a…本文实例讲述了Android View刷新机制。分享给大家供大家参考具体如下一、总体说明在Android的布局体系中父View负责刷新、布局显示子View而当子View需要刷新时则是通知父View来完成。二、代码分析1).ViewGroup的addView方法理解参数的意义和传递invalidate调用父类View的方法addViewInner方法主要做的事情是view的dispatchAttachedToWindow(AttachInfo info, int visibility)方法1).View的invalidate方法这是一个从下第向上回溯的过程每一层的父View都将自己的显示区域与传入的刷新Rect做交集。void invalidate(boolean invalidateCache) {if (ViewDebug.TRACE_HIERARCHY) {ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);}if (skipInvalidate()) {return;}if ((mPrivateFlags (DRAWN | HAS_BOUNDS)) (DRAWN | HAS_BOUNDS) ||(invalidateCache (mPrivateFlags DRAWING_CACHE_VALID) DRAWING_CACHE_VALID) ||(mPrivateFlags INVALIDATED) ! INVALIDATED || isOpaque() ! mLastIsOpaque) {mLastIsOpaque isOpaque();mPrivateFlags ~DRAWN;mPrivateFlags | DIRTY;if (invalidateCache) {mPrivateFlags | INVALIDATED;mPrivateFlags ~DRAWING_CACHE_VALID;}final AttachInfo ai mAttachInfo;final ViewParent p mParent;//noinspection PointlessBooleanExpression,ConstantConditionsif (!HardwareRenderer.RENDER_DIRTY_REGIONS) {if (p ! null ai ! null ai.mHardwareAccelerated) {// fast-track for GL-enabled applications; just invalidate the whole hierarchy// with a null dirty rect, which tells the ViewAncestor to redraw everythingp.invalidateChild(this, null);return;}}if (p ! null ai ! null) {final Rect r ai.mTmpInvalRect;r.set(0, 0, mRight - mLeft, mBottom - mTop);// Dont call invalidate -- we dont want to internally scroll// our own boundsp.invalidateChild(this, r);//调用子类的方法完成}}}2)ViewGrop的invalidateChild方法public final void invalidateChild(View child, final Rect dirty) {ViewParent parent this;final AttachInfo attachInfo mAttachInfo;if (attachInfo ! null) {final int[] location attachInfo.mInvalidateChildLocation;// 需要刷新的子View的位置location[CHILD_LEFT_INDEX] child.mLeft;location[CHILD_TOP_INDEX] child.mTop;// If the child is drawing an animation, we want to copy this flag onto// ourselves and the parent to make sure the invalidate request goes throughfinal boolean drawAnimation (child.mPrivateFlags DRAW_ANIMATION) DRAW_ANIMATION;// Check whether the child that requests the invalidate is fully opaquefinal boolean isOpaque child.isOpaque() !drawAnimation child.getAnimation() ! null;// Mark the child as dirty, using the appropriate flag// Make sure we do not set both flags at the same timefinal int opaqueFlag isOpaque ? DIRTY_OPAQUE : DIRTY;do {View view null;if (parent instanceof View) {view (View) parent;}if (drawAnimation) {if (view ! null) {view.mPrivateFlags | DRAW_ANIMATION;} else if (parent instanceof ViewRoot) {((ViewRoot) parent).mIsAnimating true;}}// If the parent is dirty opaque or not dirty, mark it dirty with the opaque// flag coming from the child that initiated the invalidateif (view ! null (view.mPrivateFlags DIRTY_MASK) ! DIRTY) {view.mPrivateFlags (view.mPrivateFlags ~DIRTY_MASK) | opaqueFlag;}parent parent.invalidateChildInParent(location, dirty);} while (parent ! null);}}public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {if ((mPrivateFlags DRAWN) DRAWN) {if ((mGroupFlags (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !FLAG_OPTIMIZE_INVALIDATE) {// 根据父View的位置偏移刷新区域dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX, location[CHILD_TOP_INDEX] - mScrollY);final int left mLeft;final int top mTop;//计算实际可刷新区域if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||(mPrivateFlags DRAW_ANIMATION) DRAW_ANIMATION) {mPrivateFlags ~DRAWING_CACHE_VALID;location[CHILD_LEFT_INDEX] left;location[CHILD_TOP_INDEX] top;return mParent;}} else {mPrivateFlags ~DRAWN ~DRAWING_CACHE_VALID;location[CHILD_LEFT_INDEX] mLeft;location[CHILD_TOP_INDEX] mTop;dirty.set(0, 0, mRight - location[CHILD_LEFT_INDEX],mBottom - location[CHILD_TOP_INDEX]);return mParent;}}return null;}这个向上回溯的过程直到ViewRoot那里结束由ViewRoot对这个最终的刷新区域做刷新ViewRoot.javapublic void invalidateChild(View child, Rect dirty) {}由ViewRoot对象的performTraversals()方法调用draw()方法发起绘制该View树值得注意的是每次发起绘图时并不会重新绘制每个View树的视图而只会重新绘制那些“需要重绘”的视图View类内部变量包含了一个标志位DRAWN当该视图需要重绘时就会为该View添加该标志位。调用流程 mView.draw()开始绘制draw()方法实现的功能如下1 、绘制该View的背景2 、为显示渐变框做一些准备操作(见5大多数情况下不需要改渐变框)3、调用onDraw()方法绘制视图本身 (每个View都需要重载该方法ViewGroup不需要实现该方法)4、调用dispatchDraw ()方法绘制子视图(如果该View类型不为ViewGroup即不包含子视图不需要重载该方法)值得说明的是ViewGroup类已经为我们重写了dispatchDraw ()的功能实现应用程序一般不需要重写该方法但可以重载父类函数实现具体的功能。4.1 dispatchDraw()方法内部会遍历每个子视图调用drawChild()去重新回调每个子视图的draw()方法(注意这个 地方“需要重绘”的视图才会调用draw()方法)。值得说明的是ViewGroup类已经为我们重写了dispatchDraw()的功能实现应用程序一般不需要重写该方法但可以重载父类函数实现具体的功能。希望本文所述对大家Android程序设计有所帮助。