View programming (3): invalidate () Source Code Analysis

Source: Internet
Author: User

View programming (2): invalidate () in the blog, I talked about the loading time of the ondraw () method of the view and the role of the invalidate () method.

In fact, it is far less simple than you think. To write this blog, let's talk about it with examples.

Package mark. zhang; import android. app. activity; import android. content. context; import android. graphics. canvas; import android. graphics. paint; import android. graphics. rectf; import android. OS. bundle; import android. util. log; import android. view. view; public class viewdrawtestactivity extends activity {// used to test static int times = 1; @ overridepublic void oncreate (bundle savedinstancestate) {super. oncreate (saved Instancestate); myview mview = new myview (this); mview. invalidate (); // setcontentview (mview);}/*** internal class, inheriting view ** @ author Mark */class myview extends view {myview (context) {super (context);} paint vpaint = new paint (); // paint style object int I = 0; // arc angle @ overrideprotected void ondraw (canvas) {super. ondraw (canvas); log. D ("mark", "This run ondraw ()" + (times ++) + "times! "); // Set the drawing style vpaint. setcolor (0xff00ffff); // paint color vpaint. setantialias (true); // vpaint with anti-aliasing. setstyle (paint. style. stroke); // draw an arc canvas. drawarc (New rectf (60,120,260,320), 0, I, true, vpaint); // arc angle if (I + = 10)> 360) {I = 0 ;} // re-paint. Execute the ondraw program again // invalidate ();}}}

The example does not change much, but the invalidate () method is called directly in the oncreate () method, for example:

mView.invalidate();

The main purpose of this operation is to check whether the ondraw () method will be triggered by calling the invalidate () method of view. Run:


The ondraw () method is not executed! Is it because the setcontentview () method is not called? Modify the oncreate () method:

@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);MyView mView = new MyView(this);mView.invalidate();setContentView(mView);mView.invalidate();}

Run again. effect:

D/mark    (  251): this run onDraw() 1 times!

Note: Only the invalidate () method in setcontentview () has enabled the function. You can call the invalidate () method of view by yourself. mview. invalidate () does not enable any function. However, calling the invalidate () method in the ondraw () method of myview can call the ondraw () method cyclically, similar to recursion.

Analyze the source code of the invalidate () method. You may find the answer here.

    /**     * Invalidate the whole view. If the view is visible, {@link #onDraw} will     * be called at some point in the future. This must be called from a     * UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.     */    public void invalidate() {        if (ViewDebug.TRACE_HIERARCHY) {            ViewDebug.trace(this, ViewDebug.HierarchyTraceType.INVALIDATE);        }        if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS)) {            mPrivateFlags &= ~DRAWN & ~DRAWING_CACHE_VALID;            final ViewParent p = mParent;            final AttachInfo ai = mAttachInfo;            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);            }        }    }

Here we can see P. invalidatechild (this, R) (the source code only looks at the key part, or you will be dizzy !), P is the viewparent instance object. Viewparent is an interface. Who cares about implementing this interface?

Through the search, we finally find the viewparen implementation class viewroot:

/** * The top of a view hierarchy, implementing the needed protocol between View * and the WindowManager.  This is for the most part an internal implementation * detail of {@link WindowManagerImpl}. * * {@hide} */@SuppressWarnings({"EmptyCatchBlock"})public final class ViewRoot extends Handler implements ViewParent, View.AttachInfo.Callbacks { }

Then, let's look at the invalidatechild () method implemented by this class:

public void invalidateChild(View child, Rect dirty) {        checkThread();        if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);        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);            }        }        mDirty.union(dirty);        if (!mWillDrawSoon) {            scheduleTraversals();        }    }

The key code is as follows:

if (!mWillDrawSoon) {            scheduleTraversals();}

This method sends a message to handler:

public void scheduleTraversals() {        if (!mTraversalScheduled) {            mTraversalScheduled = true;            sendEmptyMessage(DO_TRAVERSAL);        }}

Next, let's take a look at the implementation of the handlemessage of viewroot handler:

public void handleMessage(Message msg) {switch (msg.what) {// 、、、case DO_TRAVERSAL:// 、、、 performTraversals();}}

Call the private method private void draw (Boolean fullredrawneeded) of viewroot by using the extends mtraversals () method. The following code is critical in this method:

mView.draw(canvas);

In fact, this code is to call the draw () method of view. The key code is as follows:

if (!dirtyOpaque) onDraw(canvas);

That is to say, the ondraw () method will be called back if this method is satisfied. So far, you should understand that when we call the invalidate () method, the ondraw () method callback must meet the conditions.
Call relationship. See the sketch!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.