当前位置:网站首页>WMS you don't know
WMS you don't know
2022-07-28 02:06:00 【AD calcium milk Lalalala】
We finished the front Handler and Binder Learning from , It can be said that the foundation has been laid . If there are students who don't understand , Look at mine Framework Other articles in the column , The default here is that everyone has this foundation .
Let's think about a question first :invalidate Will trigger other View Redrawn ?
The answer is obviously yes , But why ? Many people may not be able to answer . Let's look at the system source code !
Open my sublime Text, Search for invalidate(), A lot of things come out , Then right-click ,Goto definition.
( remarks :sublime Text Global search Find->Find Files)
We'll eventually find View The path of :frameworks/base/core/java/android/view/View.java
Let's look at it first invalidate What do you mean by , At first, everyone may guess that this should mean refresh , But it actually means abandonment .
step1:
public void invalidate() {
invalidate(true);
}step2:
invalidateCache Set to true Indicates that the cache is completely discarded
public void invalidate(boolean invalidateCache) {
invalidateInternal(0, 0, mRight - mLeft,
mBottom - mTop, invalidateCache, true);
}step3:
void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
boolean fullInvalidate) {
if (mGhostView != null) {
mGhostView.invalidate(true);
return;
}
if (skipInvalidate()) {
return;
}
if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
|| (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
|| (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
|| (fullInvalidate && isOpaque() != mLastIsOpaque)) {
if (fullInvalidate) {
mLastIsOpaque = isOpaque();
mPrivateFlags &= ~PFLAG_DRAWN;
}
mPrivateFlags |= PFLAG_DIRTY;
if (invalidateCache) {
mPrivateFlags |= PFLAG_INVALIDATED;
mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
}
// Propagate the damage rectangle to the parent view.
final AttachInfo ai = mAttachInfo;
final ViewParent p = mParent;
if (p != null && ai != null && l < r && t < b) {
final Rect damage = ai.mTmpInvalRect;
damage.set(l, t, r, b);
p.invalidateChild(this, damage);
}
// Damage the entire projection receiver, if necessary.
if (mBackground != null && mBackground.isProjected()) {
final View receiver = getProjectionReceiver();
if (receiver != null) {
receiver.damageInParent();
}
}
}
}Core code :
damage.set(l, t, r, b);
p.invalidateChild(this, damage);This means that this area is handed over to the parent layout .
step4:
@Deprecated
@Override
public final void invalidateChild(View child, final Rect dirty) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null && attachInfo.mHardwareAccelerated) {
// HW accelerated fast path
onDescendantInvalidated(child, child);
return;
}
ViewParent parent = this;
if (attachInfo != null) {
// 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 & PFLAG_DRAW_ANIMATION) != 0;
// Check whether the child that requests the invalidate is fully opaque
// Views being animated or transformed are not considered opaque because we may
// be invalidating their old position and need the parent to paint behind them.
Matrix childMatrix = child.getMatrix();
final boolean isOpaque = child.isOpaque() && !drawAnimation &&
child.getAnimation() == null && childMatrix.isIdentity();
// Mark the child as dirty, using the appropriate flag
// Make sure we do not set both flags at the same time
int opaqueFlag = isOpaque ? PFLAG_DIRTY_OPAQUE : PFLAG_DIRTY;
if (child.mLayerType != LAYER_TYPE_NONE) {
mPrivateFlags |= PFLAG_INVALIDATED;
mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
}
final int[] location = attachInfo.mInvalidateChildLocation;
location[CHILD_LEFT_INDEX] = child.mLeft;
location[CHILD_TOP_INDEX] = child.mTop;
if (!childMatrix.isIdentity() ||
(mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
RectF boundingRect = attachInfo.mTmpTransformRect;
boundingRect.set(dirty);
Matrix transformMatrix;
if ((mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
Transformation t = attachInfo.mTmpTransformation;
boolean transformed = getChildStaticTransformation(child, t);
if (transformed) {
transformMatrix = attachInfo.mTmpMatrix;
transformMatrix.set(t.getMatrix());
if (!childMatrix.isIdentity()) {
transformMatrix.preConcat(childMatrix);
}
} else {
transformMatrix = childMatrix;
}
} else {
transformMatrix = childMatrix;
}
transformMatrix.mapRect(boundingRect);
dirty.set((int) Math.floor(boundingRect.left),
(int) Math.floor(boundingRect.top),
(int) Math.ceil(boundingRect.right),
(int) Math.ceil(boundingRect.bottom));
}
do {
View view = null;
if (parent instanceof View) {
view = (View) parent;
}
if (drawAnimation) {
if (view != null) {
view.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
} else if (parent instanceof ViewRootImpl) {
((ViewRootImpl) 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) {
if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&
view.getSolidColor() == 0) {
opaqueFlag = PFLAG_DIRTY;
}
if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {
view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag;
}
}
parent = parent.invalidateChildInParent(location, dirty);//1
if (view != null) {
// Account for transform on current parent
Matrix m = view.getMatrix();
if (!m.isIdentity()) {
RectF boundingRect = attachInfo.mTmpTransformRect;
boundingRect.set(dirty);
m.mapRect(boundingRect);
dirty.set((int) Math.floor(boundingRect.left),
(int) Math.floor(boundingRect.top),
(int) Math.ceil(boundingRect.right),
(int) Math.ceil(boundingRect.bottom));
}
}
} while (parent != null);
}It's a cycle , If there is a parent layout , Will always call comments 1 This method . It will eventually arrive at decorView.
step5:
This method is the top ViewRootImpl Inside
@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);//1
return null;
}step6:
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 one
localDirty.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 region
final 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();//1
}
}step7:
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable//1, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}Pay attention to the notes 1 It's about
step8:
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();//1
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
step9:
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();//1
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}step10:
private void performTraversals() {
···
performMeasure(childWidthMeasureSpec,childHeightMeasureSpec);
···
performLayout(lp, mWidth, mHeight);
···
performDraw();
}This method code is very long , Is it deja vu !
To sum up : One of them View call invalidate Method , Call back up level by level until ViewRootimpl, Then go through the drawing process again .
I believe that the appetizer in front of me has been right View Of invalidate With some understanding , Then let's ask another question :Activity How such window And view To carry out division of labor and cooperation ?
We know activity It's through window To manage view Of ,activity It is to manage the life cycle ,view Responsible for specific display .
To be continued !
边栏推荐
- Gbase 8C backup control function (IV)
- Unity universal red dot system
- The story of the third uncle
- 轻量版项目管理系统
- 【数据库数据恢复】SQL Server数据库磁盘空间不足的数据恢复案例
- Fiddler mobile packet capturing agent settings (for Huawei glory 60s)
- Gbase 8C database object size function (I)
- LeetCode第 83 场双周赛
- Embedded classic communication protocol
- 执行 Add-Migration 迁移时报 Build failed.
猜你喜欢

Redis design specification

Leveraging the blue ocean of household appliances consumption with "digital channels", the dealer online system enables enterprises to further their business

Fiddler mobile packet capturing agent settings (for Huawei glory 60s)

Small bulk quantitative stock trading record | data is the source in the quantitative system, which teaches you to build a universal data source framework

如何评估研发人员效能?软件工程师报告帮你看见每个人的贡献

2022软件测试技能 Robotframework + SeleniumLibrary + Jenkins web关键字驱动自动化实战教程

记录一次生产死锁
![Likeshop takeout ordering system [100% open source, no encryption]](/img/e6/a73aa817b5b30339d755aa53708072.png)
Likeshop takeout ordering system [100% open source, no encryption]

JS what situations can't use json Parse, json.stringify deep copy and a better deep copy method

The storage cost is reduced by 80%. How does the cost management of youzan data middle office do?
随机推荐
HyperMesh circular array - plug in
Gbase 8C recovery control function
Gbase 8C configuration setting function
What devices does devicexplorer OPC server support? This article has listed
A happy old age
N32l43x FLASH read \ write \ erase operation summary
Traversal and properties of binary trees
GBase 8c 事务ID和快照
你所不知道的WMS
云原生爱好者周刊:Prometheus 架构演进之路
Leetcode high frequency question 128. the longest continuous sequence, which is often tested in interviews with Internet companies
软件测试面试题:为什要在一个团队中开展测试工作?
Favorite songs
执行 Add-Migration 迁移时报 Build failed.
Redis design specification
The petrochemical industry is facing the tide of rising prices, and the digital dealer distribution system platform enables dealers and stores
网易云仿写
Zkrollup learning materials summary
GBase 8c 事务ID和快照(一)
Redis设计规范