国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android View刷新機制實例分析

2020-04-11 10:45:54
字體:
來源:轉載
供稿:網友

本文實例講述了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,ConstantConditions      if (!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 everything          p.invalidateChild(this, null);          return;        }      }      if (p != null && ai != null) {        final Rect r = ai.mTmpInvalRect;        r.set(0, 0, mRight - mLeft, mBottom - mTop);        // Don't call invalidate -- we don't want to internally scroll        // our own bounds        p.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 through    final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;    // Check whether the child that requests the invalidate is fully opaque    final 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 time    final 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 invalidate      if (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.java

public 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類已經為我們重寫了dispatch

Draw()的功能實現,應用程序一般不需要重寫該方法,但可以重載父類函數實現具體的功能。

更多關于Android相關內容感興趣的讀者可查看本站專題:《Android開發入門與進階教程》、《Android多媒體操作技巧匯總(音頻,視頻,錄音等)》、《Android基本組件用法總結》、《Android視圖View技巧總結》、《Android布局layout技巧總結》及《Android控件用法總結

希望本文所述對大家Android程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 岫岩| 昌黎县| 宕昌县| 信阳市| 大田县| 博客| 湖北省| 岳普湖县| 淳化县| 怀柔区| 绍兴县| 新蔡县| 岳阳县| 汶上县| 库伦旗| 阿图什市| 富民县| 屏边| 沾化县| 安徽省| 武山县| 蕉岭县| 香河县| 鹤峰县| 兴国县| 临朐县| 肥乡县| 柳江县| 广昌县| 黔江区| 京山县| 云阳县| 乌鲁木齐县| 定结县| 新安县| 常德市| 玉林市| 府谷县| 景泰县| 南郑县| 锡林郭勒盟|