当前位置:网站首页>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 !
边栏推荐
- Five basic data structures of redis
- Enterprise operation and maintenance practice - using aliyun container image service to pull and build images of overseas GCR and quay warehouses
- 机器学习如何做到疫情可视化——疫情数据分析与预测实战
- Data security and privacy computing summit - provable security: Learning
- What devices does devicexplorer OPC server support? This article has listed
- 自定义类型:结构体,枚举,联合
- GBase 8c 事务ID和快照
- What is method and methodology: understand the underlying logic of self-improvement
- 如何评估研发人员效能?软件工程师报告帮你看见每个人的贡献
- 二叉树的遍历和性质
猜你喜欢

数字经济才是未来经济发展的核心

FreeRTOS kernel summary

Vxe Table/Grid 单元格分组合并

Open source flight control (Px4, ardupilot)

以“数字化渠道”撬动家用电器消费蓝海,经销商在线系统让企业生意更进一步

53:第五章:开发admin管理服务:6:开发【admin管理员退出登录,接口】;(一个点:我们想要修改一个采用了某种编码方式的值时,新的值最好也按照这种编码方式编码后,再去修改;)

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

记录一次生产死锁

54:第五章:开发admin管理服务:7:人脸入库流程;人脸登录流程;浏览器开启视频调试模式(以便能够在本机的不安全域名的情况下,也能去开启摄像头);

处理数据 给数据换名字
随机推荐
synchronized详解
The petrochemical industry is facing the tide of rising prices, and the digital dealer distribution system platform enables dealers and stores
Gbase 8C snapshot synchronization function
FreeRTOS kernel summary
【面试:并发篇28:volatile】有序性
【网站搭建】使用acme.sh更新ssl证书:将zerossl改为letsencrypt
Use of classes in typescript
Five basic data structures of redis
Open source flight control (Px4, ardupilot)
华为APP UI自动化测试岗面试真题,真实面试经历。
zkrollup学习资料汇总
GBase 8c 事务ID和快照(四)
Software test interview question: please introduce the meaning of various test types in detail?
Gbase 8C transaction ID and snapshot (V)
go 学习02 基础知识
你所不知道的WMS
The storage cost is reduced by 80%. How does the cost management of youzan data middle office do?
Gbase 8C transaction ID and snapshot
Enterprise operation and maintenance practice - using aliyun container image service to pull and build images of overseas GCR and quay warehouses
Cloud native enthusiast weekly: the evolution of Prometheus architecture