日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android 刷新view位置,Android View刷新机制实例分析

發(fā)布時間:2025/3/12 Android 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 刷新view位置,Android View刷新机制实例分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文實例講述了Android View刷新機制。分享給大家供大家參考,具體如下:

一、總體說明

在Android的布局體系中,父View負責刷新、布局顯示子View;而當子View需要刷新時,則是通知父View來完成。

二、代碼分析

1).ViewGroup的addView方法,理解參數的意義和傳遞

invalidate調用父類View的方法

addViewInner方法主要做的事情是

view的dispatchAttachedToWindow(AttachInfo info, int visibility)方法

1).View的invalidate方法,這是一個從下第向上回溯的過程,每一層的父View都將自己的顯示區(qū)域與傳入的刷新

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的位置,偏移刷新區(qū)域

dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX, location[CHILD_TOP_INDEX] - mScrollY);

final int left = mLeft;

final int top = mTop;

//計算實際可刷新區(qū)域

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對這個最終的刷新區(qū)域做刷新

ViewRoot.java

public void invalidateChild(View child, Rect dirty) {

}

由ViewRoot對象的performTraversals()方法調用draw()方法發(fā)起繪制該View樹,值得注意的是每次發(fā)起繪圖時,并不會重新繪制每個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 刷新view位置,Android View刷新机制实例分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。