深入理解android view 生命周期

非淡泊无以明志,非宁静无以致远。这篇文章主要讲述深入理解android view 生命周期相关的知识,希望能为你提供帮助。
作为自定义 view 的基础,如果不了解Android   view 的生命周期 , 那么你将会在后期的维护中发现这样那样的问题 .......
做过一段时间android 开发的同学都知道,一般 onXXX 函数都是系统的回调函数。而这篇 blog 也是基于这个思想(或许有点笨

深入理解android view 生命周期

文章图片
)......


首先来看三分   创建view 的 日志信息 (自定义View 配置到xml文件中):
android:visibility=gone
[html] view plain copy
  1. 03-25  19:56:55.934:  D/yyyyy(11493):  onVisibilityChanged--------=====   
  2. 03-25  19:56:55.934:  D/yyyyy(11493):  construct  2  parameters  .   
  3. 03-25  19:56:55.934:  E/yyyyy(11493):  onFinishInflate   
  4. 03-25  19:56:55.934:  D/yyyyy(11493):  onVisibilityChanged--------=====   
  5. 03-25  19:56:55.934:  D/yyyyy(11493):  onVisibilityChanged--------=====   
  6. 03-25  19:56:55.944:  D/yyyyy(11493):  onRtlPropertiesChanged--------=====   
  7. 03-25  19:56:55.954:  D/yyyyy(11493):  onRtlPropertiesChanged--------=====   
  8. 03-25  19:56:55.954:  E/yyyyy(11493):  onAttachedToWindow   
  9. 03-25  19:56:55.954:  D/yyyyy(11493):  onWindowVisibilityChanged--------=====   
  10. 03-25  19:56:55.974:  D/yyyyy(11493):  onWindowFocusChanged--------=====   

android:visibility=invisible
[html] view plain copy
  1. 03-25  19:57:38.204:  D/yyyyy(11694):  onVisibilityChanged--------=====   
  2. 03-25  19:57:38.204:  D/yyyyy(11694):  construct  2  parameters  .   
  3. 03-25  19:57:38.204:  E/yyyyy(11694):  onFinishInflate   
  4. 03-25  19:57:38.204:  D/yyyyy(11694):  onVisibilityChanged--------=====   
  5. 03-25  19:57:38.204:  D/yyyyy(11694):  onVisibilityChanged--------=====   
  6. 03-25  19:57:38.224:  D/yyyyy(11694):  onRtlPropertiesChanged--------=====   
  7. 03-25  19:57:38.224:  D/yyyyy(11694):  onRtlPropertiesChanged--------=====   
  8. 03-25  19:57:38.224:  E/yyyyy(11694):  onAttachedToWindow   
  9. 03-25  19:57:38.224:  D/yyyyy(11694):  onWindowVisibilityChanged--------=====   
  10. 03-25  19:57:38.224:  D/yyyyy(11694):  onMeasure  ,  width  :  1080    ;   height:  1557   
  11. 03-25  19:57:38.224:  D/yyyyy(11694):  onMeasure  ,  width  :  144    ;   height:  1500   
  12. 03-25  19:57:38.234:  D/yyyyy(11694):  onSizeChanged   
  13. 03-25  19:57:38.234:  I/yyyyy(11694):  onLayout  -->   l:  0    ;   r  :  144    ;   t:  57    ;   b:  201    :  changed  :true   
  14. 03-25  19:57:38.254:  D/yyyyy(11694):  onMeasure  ,  width  :  1080    ;   height:  1557   
  15. 03-25  19:57:38.254:  D/yyyyy(11694):  onMeasure  ,  width  :  144    ;   height:  1500   
  16. 03-25  19:57:38.254:  I/yyyyy(11694):  onLayout  -->   l:  0    ;   r  :  144    ;   t:  57    ;   b:  201    :  changed  :false   
  17. 03-25  19:57:38.264:  D/yyyyy(11694):  onWindowFocusChanged--------=====   

android:visibility=visible
[html] view plain copy
  1. 03-25  19:55:15.434:  D/yyyyy(11304):  construct  2  parameters  .   
  2. 03-25  19:55:15.434:  E/yyyyy(11304):  onFinishInflate   
  3. 03-25  19:55:15.434:  D/yyyyy(11304):  onVisibilityChanged--------=====   
  4. 03-25  19:55:15.434:  D/yyyyy(11304):  onVisibilityChanged--------=====   
  5. 03-25  19:55:15.454:  D/yyyyy(11304):  onRtlPropertiesChanged--------=====   
  6. 03-25  19:55:15.454:  D/yyyyy(11304):  onRtlPropertiesChanged--------=====   
  7. 03-25  19:55:15.454:  E/yyyyy(11304):  onAttachedToWindow   
  8. 03-25  19:55:15.454:  D/yyyyy(11304):  onWindowVisibilityChanged--------=====   
  9. 03-25  19:55:15.454:  D/yyyyy(11304):  onMeasure  ,  width  :  1080    ;   height:  1557   
  10. 03-25  19:55:15.454:  D/yyyyy(11304):  onMeasure  ,  width  :  144    ;   height:  1500   
  11. 03-25  19:55:15.464:  D/yyyyy(11304):  onSizeChanged   
  12. 03-25  19:55:15.464:  I/yyyyy(11304):  onLayout  -->   l:  0    ;   r  :  144    ;   t:  57    ;   b:  201    :  changed  :true   
  13. 03-25  19:55:15.474:  D/yyyyy(11304):  onMeasure  ,  width  :  1080    ;   height:  1557   
  14. 03-25  19:55:15.474:  D/yyyyy(11304):  onMeasure  ,  width  :  144    ;   height:  1500   
  15. 03-25  19:55:15.474:  I/yyyyy(11304):  onLayout  -->   l:  0    ;   r  :  144    ;   t:  57    ;   b:  201    :  changed  :false   
  16. 03-25  19:55:15.474:  D/yyyyy(11304):  onDraw--------=====   
  17. 03-25  19:55:15.484:  D/yyyyy(11304):  onWindowFocusChanged--------=====   

1、从中不难看到view 默认为可见的 , 不是默认值时先调用     onVisibilityChanged   , 但是此时该view 的任何位置信息都不知道。
2、可见性改变后才是调用带有两个参数的构造函数
3、从xml 文件中 inflate 完成
4、将view 加到 window 中               (  View 是gone 的 ,那么View创建生命周期也就结束  )
5、测量view的长宽                           (  onMeasure  )
6、定位View 在父View中的位置       (  onLayout  )--> (View 是invisible , View 创建生命周期结束)
7、onDraw                                         ( 只有可见的   View   才在   window   中绘制  )


在代码中构造View:
setContentView(new CusView(this))输入日志信息如下:
 
[html] view plain copy
  1. 03-25  20:37:51.284:  E/yyyyy(12530):  construct  1  parameter   
  2. 03-25  20:37:51.294:  D/yyyyy(12530):  onVisibilityChanged--------=====   
  3. 03-25  20:37:51.314:  D/yyyyy(12530):  onVisibilityChanged--------=====   
  4. 03-25  20:37:51.314:  D/yyyyy(12530):  onRtlPropertiesChanged--------=====   
  5. 03-25  20:37:51.314:  D/yyyyy(12530):  onRtlPropertiesChanged--------=====   
  6. 03-25  20:37:51.314:  E/yyyyy(12530):  onAttachedToWindow   
  7. 03-25  20:37:51.314:  D/yyyyy(12530):  onWindowVisibilityChanged--------=====   
  8. 03-25  20:37:51.314:  D/yyyyy(12530):  onMeasure  ,  width  :  1080    ;   height:  1557   
  9. 03-25  20:37:51.314:  D/yyyyy(12530):  onSizeChanged   
  10. 03-25  20:37:51.324:  I/yyyyy(12530):  onLayout  -->   l:  0    ;   r  :  1080    ;   t:  0    ;   b:  1557    :  changed  :true   
  11. 03-25  20:37:51.324:  D/yyyyy(12530):  onMeasure  ,  width  :  1080    ;   height:  1557   
  12. 03-25  20:37:51.324:  I/yyyyy(12530):  onLayout  -->   l:  0    ;   r  :  1080    ;   t:  0    ;   b:  1557    :  changed  :false   
  13. 03-25  20:37:51.324:  D/yyyyy(12530):  onDraw--------=====   
  14. 03-25  20:37:51.344:  D/yyyyy(12530):  onWindowFocusChanged--------=====   
从测试结果来看,默认情况下view的长和宽默认和父 view 的长和宽一致 。


虽然调用了onDraw 函数,但是在屏幕上却看不到任何内容,什么原因?
当看不到任何内容时,请先检查 View要绘制的内容是否制定。


为什么我指定了LayoutParameters,却没有效果?
在不恰当的生命周期中指定LayoutParameters,会被忽略掉,比如如下代码:
 
[java] view plain copy
  1. @Override   
  2.         protected  void  onCreate(Bundle  savedInstanceState)  {   
  3.                 super.onCreate(savedInstanceState);    
  4.                 //  setContentView(R.layout.activity_main);    
  5.                 view  =  new  CusView(this);    
  6.                 view.setImageResource(R.drawable.ic_launcher);    
  7.                 FrameLayout.LayoutParams  params  =  new  FrameLayout.LayoutParams(70,  70);    
  8.                 view.setLayoutParams(params);    
  9.                 setContentView(view);    
  10.         }   
正确的方法应该是放到     onWindowFocusChanged 方法获取到焦点后再指定LayoutParameters,如下代码:
 
[java] view plain copy
  1. @Override   
  2.         public  void  onWindowFocusChanged(boolean  hasFocus)  {   
  3.                 //  TODO  Auto-generated  method  stub   
  4.                 super.onWindowFocusChanged(hasFocus);    
  5.                 if  (hasFocus)  {   
  6.                         view.setImageResource(R.drawable.ic_launcher);    
  7.                         FrameLayout.LayoutParams  params  =  new  FrameLayout.LayoutParams(70,  70);    
  8.                         view.setLayoutParams(params);    
  9.                 }   
  10.         }   

为什么我指定LayoutParameters参数时报异常?异常信息如下:
 
[html] view plain copy
  1. java.lang.ClassCastException:  android.view.ViewGroup$LayoutParams  cannot  be  cast  to  android.view.ViewGroup$MarginLayoutParams   
 
java.lang.Object

  ? android.view.ViewGroup.LayoutParams
    ? onWindowFocusChanged--------=====   
  • 03-25  21:15:35.484:  D/yyyyy(14589):  onWindowVisibilityChanged--------=====   
  • 03-25  21:15:35.504:  D/yyyyy(14589):  onDetachedFromWindow--------=====   
android:visibility=gone
[html] view plain copy
  1. 03-25  21:16:09.964:  D/yyyyy(14736):  onWindowFocusChanged--------=====   
  2. 03-25  21:16:10.054:  D/yyyyy(14736):  onWindowVisibilityChanged--------=====   
  3. 03-25  21:16:10.064:  D/yyyyy(14736):  onDetachedFromWindow--------=====   
android:visibility=invisible
[html] view plain copy
  1. 03-25  21:16:42.534:  D/yyyyy(14860):  onWindowFocusChanged--------=====   
  2. 03-25  21:16:42.594:  D/yyyyy(14860):  onWindowVisibilityChanged--------=====   
  3. 03-25  21:16:42.614:  D/yyyyy(14860):  onDetachedFromWindow--------=====   

从以上内容可以看到,visibility属性对view的销毁流程没有影响。

综上所述:View 的关键生命周期为     [改变可见性]   -->     构造View   -->       onFinishInflate   -->   onAttachedToWindow   -->   onMeasure   -->   onSizeChanged   -->   onLayout   -->     onDraw   -->   onDetackedFromWindow
 
【深入理解android view 生命周期】

最后给出一小段代码用于在屏幕上拖动view(通过修改view的 layout ):
[java] view plain copy
  1. private  float  mDownX,  mDownY,  x,  y;    
  2.         private  int  dx,  dy,  il,  ir,  it,  ib;    
  3.         @Override   
  4.         public  boolean  onTouchEvent(MotionEvent  event)  {   
  5.                 x  =  event.getX();    
  6.                 y  =  event.getY();    
  7.                 switch  (event.getAction())  {   
  8.                         case  MotionEvent.ACTION_DOWN:   
  9.                                 mDownX  =  event.getX();    
  10.                                 mDownY  =  event.getY();    
  11.                                 il  =  getLeft();    
  12.                                 ir  =  getRight();    
  13.                                 it  =  getTop();    
  14.                                 ib  =  getBottom();    
  15.                                 break;    
  16.                         case  MotionEvent.ACTION_MOVE:   
  17.                         case  MotionEvent.ACTION_UP:   
  18.                                 dx  +=  Math.round(x  -  mDownX);    
  19.                                 dy  +=  Math.round(y  -  mDownY);    
  20.                                 layout(il  +  dx,  it  +  dy,  ir  +  dx,  ib  +  dy);    
  21.                                 break;    
  22.                 }   
  23.                 return  true;    
  24.         } 














    推荐阅读