代码改变世界

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

2011-12-14 16:38  tang768168  阅读(279)  评论(0编辑  收藏  举报

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

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

  1. D/mark    ( 2924): onMeasure() is invoked!  
  2. D/mark    ( 2924): onMeasure() is invoked!  
  3. D/mark    ( 2924): onMeasure() is invoked!  
  4. D/mark    ( 2924): onMeasure() is invoked!  
  5. D/mark    ( 2924): onMeasure() is invoked!  
  6. D/mark    ( 2924): onMeasure() is invoked!  
  7. D/mark    ( 2924): onMeasure() is invoked!  
  8. D/mark    ( 2924): onMeasure() is invoked!  
  9. D/mark    ( 2924): onMeasure() is invoked!  

百思不得其解,只好再次看源码,找答案。

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

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

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

  1. public final void measure(int widthMeasureSpec, int heightMeasureSpec) {  
  2.         if ((mPrivateFlags & FORCE_LAYOUT) == FORCE_LAYOUT ||  
  3.                 widthMeasureSpec != mOldWidthMeasureSpec ||  
  4.                 heightMeasureSpec != mOldHeightMeasureSpec) {  
  5.   
  6.             // first clears the measured dimension flag  
  7.             mPrivateFlags &= ~MEASURED_DIMENSION_SET;  
  8.   
  9.             if (ViewDebug.TRACE_HIERARCHY) {  
  10.                 ViewDebug.trace(this, ViewDebug.HierarchyTraceType.ON_MEASURE);  
  11.             }  
  12.   
  13.             // measure ourselves, this should set the measured dimension flag back  
  14.             onMeasure(widthMeasureSpec, heightMeasureSpec);  
  15.   
  16.             // flag not set, setMeasuredDimension() was not invoked, we raise  
  17.             // an exception to warn the developer  
  18.             if ((mPrivateFlags & MEASURED_DIMENSION_SET) != MEASURED_DIMENSION_SET) {  
  19.                 throw new IllegalStateException("onMeasure() did not set the"  
  20.                         + " measured dimension by calling"  
  21.                         + " setMeasuredDimension()");  
  22.             }  
  23.   
  24.             mPrivateFlags |= LAYOUT_REQUIRED;  
  25.         }  
  26.   
  27.         mOldWidthMeasureSpec = widthMeasureSpec;  
  28.         mOldHeightMeasureSpec = heightMeasureSpec;  
  29. }  

可以看出两个问题:

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

2. 调用了onMeasure()方法:

  1. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  2.         setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),  
  3.         getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));  
  4. }  

该方法是一个protected方法,是一个回调方法,一般需要子类去重写。

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

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

 

转载地址:http://blog.csdn.net/androidbluetooth/article/details/6704314