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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

invalidate()源码分析

發布時間:2023/11/28 生活经验 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 invalidate()源码分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

invalidate()方法的使用,就是重新觸發一次View的繪制流程。

入口在View類中,

public void invalidate() {invalidate(true);
}public void invalidate(boolean invalidateCache) {invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
}

在 invalidateInternal(...) 中 ,調用

p.invalidateChild(this, damage); //p為ViewParent

ViewGroup繼承View,實現了 ViewParent,在ViewGroup的invalidateChild()方法中有個do while 循環,循環中關鍵代碼:

parent = parent.invalidateChildInParent(location, dirty);

ViewRootImpl實現了ViewParent,在ViewRootImpl中,

@Override
public void invalidateChild(View child, Rect dirty) {invalidateChildInParent(null, dirty);
}@Override
public ViewParent invalidateChildInParent(int[] location, Rect dirty) {checkThread();if (DEBUG_DRAW) Log.v(mTag, "Invalidate child: " + dirty);if (dirty == null) {invalidate();return null;} else if (dirty.isEmpty() && !mIsAnimating) {return null;}if (mCurScrollY != 0 || mTranslator != null) {mTempRect.set(dirty);dirty = mTempRect;if (mCurScrollY != 0) {dirty.offset(0, -mCurScrollY);}if (mTranslator != null) {mTranslator.translateRectInAppWindowToScreen(dirty);}if (mAttachInfo.mScalingRequired) {dirty.inset(-1, -1);}}invalidateRectOnScreen(dirty);return null;
}private void invalidateRectOnScreen(Rect dirty) {final Rect localDirty = mDirty;if (!localDirty.isEmpty() && !localDirty.contains(dirty)) {mAttachInfo.mSetIgnoreDirtyState = true;mAttachInfo.mIgnoreDirtyState = true;}// Add the new dirty rect to the current onelocalDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom);// Intersect with the bounds of the window to skip// updates that lie outside of the visible regionfinal float appScale = mAttachInfo.mApplicationScale;final boolean intersected = localDirty.intersect(0, 0,(int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));if (!intersected) {localDirty.setEmpty();}if (!mWillDrawSoon && (intersected || mIsAnimating)) {scheduleTraversals();}
}

invalidateChild(..)方法調用invalidateChildInParent(..),

invalidateChildInParent(..)方法調用invalidateRectOnScreen(dirty),

invalidateRectOnScreen(dirty)方法中最終會調用scheduleTraversals()

scheduleTraversals()這個方法很關鍵,會通過一系列的調用最終調用TraversalRunnable.run()方法,然后調用doTraversal()方法,doTraversal()中調用performTraversals()。

void doTraversal() {if (mTraversalScheduled) {mTraversalScheduled = false;mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);if (mProfile) {Debug.startMethodTracing("ViewAncestor");}performTraversals();if (mProfile) {Debug.stopMethodTracing();mProfile = false;}}
}

performTraversals()主要做三件事:

performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

performLayout(lp, mWidth, mHeight);

performDraw();

最后會調用View的繪制方法:

measure(childWidthMeasureSpec, childHeightMeasureSpec);

layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());

draw(fullRedrawNeeded);

至此,整個invalidate()流程結束,貫穿著一個布局或View的所有子view,以下是流程圖:

?

?

總結

以上是生活随笔為你收集整理的invalidate()源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。

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