Android custom View series
- Android custom View Paint draws text and lines
- Android custom View Precautions
- Canvas for Android custom View
- Android custom View image shape effects – easy to achieve rounded corners and round images
- Android custom View dual buffering mechanism and SurfaceView
- Android custom View invalidate method and postInvalidate method
- Android custom View Window, View View PL and View of the three processes
- Android custom View image color processing
RequestLayout (invalidate) : invalidate (requestLayout) : Invalidate (requestLayout) : Invalidate (requestLayout) : Invalidate (requestLayout) : Invalidate (requestLayout
Conclusion for those who can’t wait:
RequestLayout causes the View’s onMeasure, onLayout, and onDraw methods to be called. The invalidate method only causes the View’s onDraw method to be called
RequestLayout method source code analysis
//View.class
@CallSuper
public void requestLayout() {
if(mMeasureCache ! = null) mMeasureCache.clear();if(mAttachInfo ! = null && mAttachInfo.mViewRequestingLayout == null) { // Only trigger request-during-layout logicif this is the view requesting it,
// not the views in its parent hierarchy
ViewRootImpl viewRoot = getViewRootImpl();
if(viewRoot ! = null && viewRoot.isInLayout()) {if(! viewRoot.requestLayoutDuringLayout(this)) {return; } } mAttachInfo.mViewRequestingLayout = this; } / / set PFLAG_FORCE_LAYOUT tag, it will lead to remeasure and layout mPrivateFlags | = PFLAG_FORCE_LAYOUT; / / set PFLAG_INVALIDATED will redraw mPrivateFlags | = PFLAG_INVALIDATED;if(mParent ! = null && ! MParent. IsLayoutRequested ()) {/ / continuously call requestLayout of upper View method mParent. RequestLayout (). }if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
mAttachInfo.mViewRequestingLayout = null;
}
}
Copy the code
In the requestLayout method of the View, the flag bit of the View is first set. PFLAG_FORCE_LAYOUT indicates that the View is to be relaid, and PFLAG_INVALIDATED indicates that the View is to be redrawn.
The requestLayout method calls the parent layout’s requestLayout method one layer at a time, setting the PFLAG_FORCE_LAYOUT flag, and ultimately calling the ViewRootImpl requestLayout method.
//ViewRootImpl.class
@Override
public void requestLayout() {
if(! mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested =true; scheduleTraversals(); }}Copy the code
As you can see, the requestLayout method in ViewRootImpl calls the scheduleTraversals method, and the scheduleTraversals method finally calls the performTraversals method to execute the View’s three main processes, Call the View’s measure, Layout, and draw methods, respectively.
public final void measure(int widthMeasureSpec, int heightMeasureSpec) { ... final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; .if (forceLayout || needsLayout) {
// first clears the measured dimension flag
mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
resolveRtlPropertiesIfNeeded();
int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
if (cacheIndex < 0 || sIgnoreMeasureCache) {
// measure ourselves, this should setOnMeasure (widthMeasureSpec, heightMeasureSpec) onMeasure(widthMeasureSpec, heightMeasureSpec); mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; }else {
long value = mMeasureCache.valueAt(cacheIndex);
// Casting a long to int drops the high 32 bits, no mask needed
setMeasuredDimensionRaw((int) (value >> 32), (int) value); mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT; } / / set PFLAG_LAYOUT_REQUIRED labeling for layout method mPrivateFlags | = PFLAG_LAYOUT_REQUIRED; }... }Copy the code
Since the requestLayout method sets the PFLAG_FORCE_LAYOUT flag bit, the measure method calls the onMeasure method to remeasure the View. The PFLAG_LAYOUT_REQUIRED flag bit is finally set in the measure method so that the onLayout method is executed in the Layout method for the layout process.
public void layout(int l, int t, int r, int b) { ... // Since the PFLAG_LAYOUT_REQUIRED bit is set in the measure method, the onLayout method is called for layoutif (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
if (shouldDrawRoundScrollbar()) {
if(mRoundScrollbarRenderer == null) { mRoundScrollbarRenderer = new RoundScrollbarRenderer(this); }}else{ mRoundScrollbarRenderer = null; } // Cancel the PFLAG_LAYOUT_REQUIRED flag bit mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED; ListenerInfo li = mListenerInfo;if(li ! = null && li.mOnLayoutChangeListeners ! = null) { ArrayList<OnLayoutChangeListener> listenersCopy = (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone(); int numListeners = listenersCopy.size();for(int i = 0; i < numListeners; ++i) { listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); }} // Cancel the PFLAG_FORCE_LAYOUT flag bit mPrivateFlags &= ~PFLAG_FORCE_LAYOUT; mPrivateFlags3 |= PFLAG3_IS_LAID_OUT; }Copy the code
Since the PFLAG_LAYOUT_REQUIRED bit is set in the measure method, the onLayout method is called in the Layout method to perform the layout process. Finally, the PFLAG_FORCE_LAYOUT and PFLAG_LAYOUT_REQUIRED flag bits are cleared.
conclusion
(1) The requestLayout method flags PFLAG_FORCE_LAYOUT, and then calls the parent requestLayout method one layer at a time and flags PFLAG_FORCE_LAYOUT. The requestLayout method in ViewRootImpl is called to start the View’s three processes. The marked View is then measured, laid out, and drawn using onMeasure, onLayout, and onDraw methods.
The invalidate method is similar to the requestLayout method. However, the Invalidate method does not flag PFLAG_FORCE_LAYOUT, so it does not perform the measurement and layout process. Instead, it redraws the View that needs to be redrawn. That is, only the onDraw method is called, not the onMeasure and onLayout methods.
test
Simply customize a View, and then design two buttons, click on the View respectively call requestLayout method and invalidate method, View the log.
Call the View’s invalidate method after clicking the invalidate button
Click the Layout button to call the View’s requestLayout method
Welcome to follow my wechat public number, and make progress with me every day!Copy the code