View编程(6): 自定义View_02_ApiDemo源码研究

阅读这篇博客之前,假设你已经研究了 View编程(5): 自定义View_01_ApiDemo源码研究 提供的实例。

当时,很奇怪为什么会出现这样的log:(在手机上测试结果,不是在模拟器上。)

D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
D/mark    ( 2924): onMeasure() is invoked!
百思不得其解,只好再次看源码,找答案。

在博客 View编程(3): invalidate()源码分析 分析过invalidate()源码,从而也分析了 draw()、以及onDraw()方法之间的关系。

其实,onMeasure()这个回调方法与onDraw()差不多,也是通过measure()回调。

先看一下,measure()、onMeasure()方法源码。

public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
        if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||
                widthMeasureSpec != mOldWidthMeasureSpec ||
                heightMeasureSpec != mOldHeightMeasureSpec) {

            // first clears the measured dimension flag
            mPrivateFlags &= ~MEASURED_DIMENSION_SET;

            if (ViewDebug.TRACE_HIERARCHY) {
                ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);
            }

            // measure ourselves, this should set the measured dimension flag back
            onMeasure(widthMeasureSpec, heightMeasureSpec);

            // flag not set, setMeasuredDimension() was not invoked, we raise
            // an exception to warn the developer
            if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {
                throw new IllegalStateException("onMeasure() did not set the"
                        + " measured dimension by calling"
                        + " setMeasuredDimension()");
            }

            mPrivateFlags |= LAYOUT_REQUIRED;
        }

        mOldWidthMeasureSpec = widthMeasureSpec;
        mOldHeightMeasureSpec = heightMeasureSpec;
}
可以看出两个问题:

1. 该方法是一个final方法,不可以被子类重写。只可以被子类继承。

2. 调用了onMeasure()方法:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
        getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
该方法是一个protected方法,是一个回调方法,一般需要子类去重写。

那么,什么时候调用measure()方法?通过上面分析可以知道,肯定是被View自己调用。究竟如何调用,还得看看invalidate()源码。这里不再赘述。

下面把调用关系草图显示如下,如果有兴趣的话,自己search吧!






©️2020 CSDN 皮肤主题: 酷酷鲨 设计师:CSDN官方博客 返回首页