Android View的生命周期详解

View生命周期相关方法:

  1. onFinishInflate() 当View中所有的子控件均被映射成xml后触发
  2. onMeasure( int ,  int ) 确定所有子元素的大小
  3. onLayout( boolean ,  int ,  int ,  int ,  int ) 当View分配所有的子元素的大小和位置时触发
  4. onSizeChanged( int ,  int ,  int ,  int ) 当view的大小发生变化时触发
  5. onDraw(Canvas) view渲染内容的细节
  6. onKeyDown( int , KeyEvent) 有按键按下后触发
  7. onKeyUp( int , KeyEvent) 有按键按下后弹起时触发
  8. onTrackballEvent(MotionEvent) 轨迹球事件
  9. onTouchEvent(MotionEvent) 触屏事件
  10. onFocusChanged( boolean ,  int , Rect) 当View获取或失去焦点时触发
  11. onWindowFocusChanged( boolean ) 当窗口包含的view获取或失去焦点时触发
  12. onAttachedToWindow() 当view被附着到一个窗口时触发
  13. onDetachedFromWindow() 当view离开附着的窗口时触发,Android123提示该方法和  onAttachedToWindow() 是相反的。
  14. onWindowVisibilityChanged( int ) 当窗口中包含的可见的view发生变化时触发

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

首先来看三分 创建view 的 日志信息 (自定义View 配置到xml文件中):

android:visibility=gone

?


1

2

3

4

5

6

7

8

9

10

03-25 19:56:55.934: D/yyyyy(11493): onVisibilityChanged--------=====

03-25 19:56:55.934: D/yyyyy(11493): construct 2 parameters .

03-25 19:56:55.934: E/yyyyy(11493): onFinishInflate

03-25 19:56:55.934: D/yyyyy(11493): onVisibilityChanged--------=====

03-25 19:56:55.934: D/yyyyy(11493): onVisibilityChanged--------=====

03-25 19:56:55.944: D/yyyyy(11493): onRtlPropertiesChanged--------=====

03-25 19:56:55.954: D/yyyyy(11493): onRtlPropertiesChanged--------=====

03-25 19:56:55.954: E/yyyyy(11493): onAttachedToWindow

03-25 19:56:55.954: D/yyyyy(11493): onWindowVisibilityChanged--------=====

03-25 19:56:55.974: D/yyyyy(11493): onWindowFocusChanged--------=====


android:visibility=invisible

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

03-25 19:57:38.204: D/yyyyy(11694): onVisibilityChanged--------=====

03-25 19:57:38.204: D/yyyyy(11694): construct 2 parameters .

03-25 19:57:38.204: E/yyyyy(11694): onFinishInflate

03-25 19:57:38.204: D/yyyyy(11694): onVisibilityChanged--------=====

03-25 19:57:38.204: D/yyyyy(11694): onVisibilityChanged--------=====

03-25 19:57:38.224: D/yyyyy(11694): onRtlPropertiesChanged--------=====

03-25 19:57:38.224: D/yyyyy(11694): onRtlPropertiesChanged--------=====

03-25 19:57:38.224: E/yyyyy(11694): onAttachedToWindow

03-25 19:57:38.224: D/yyyyy(11694): onWindowVisibilityChanged--------=====

03-25 19:57:38.224: D/yyyyy(11694): onMeasure , width : 1080  ; height: 1557

03-25 19:57:38.224: D/yyyyy(11694): onMeasure , width : 144  ; height: 1500

03-25 19:57:38.234: D/yyyyy(11694): onSizeChanged

03-25 19:57:38.234: I/yyyyy(11694): onLayout --> l: 0  ; r : 144  ; t: 57  ; b: 201  : changed :true

03-25 19:57:38.254: D/yyyyy(11694): onMeasure , width : 1080  ; height: 1557

03-25 19:57:38.254: D/yyyyy(11694): onMeasure , width : 144  ; height: 1500

03-25 19:57:38.254: I/yyyyy(11694): onLayout --> l: 0  ; r : 144  ; t: 57  ; b: 201  : changed :false

03-25 19:57:38.264: D/yyyyy(11694): onWindowFocusChanged--------=====

android:visibility=visible

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

03-25 19:55:15.434: D/yyyyy(11304): construct 2 parameters .

03-25 19:55:15.434: E/yyyyy(11304): onFinishInflate

03-25 19:55:15.434: D/yyyyy(11304): onVisibilityChanged--------=====

03-25 19:55:15.434: D/yyyyy(11304): onVisibilityChanged--------=====

03-25 19:55:15.454: D/yyyyy(11304): onRtlPropertiesChanged--------=====

03-25 19:55:15.454: D/yyyyy(11304): onRtlPropertiesChanged--------=====

03-25 19:55:15.454: E/yyyyy(11304): onAttachedToWindow

03-25 19:55:15.454: D/yyyyy(11304): onWindowVisibilityChanged--------=====

03-25 19:55:15.454: D/yyyyy(11304): onMeasure , width : 1080  ; height: 1557

03-25 19:55:15.454: D/yyyyy(11304): onMeasure , width : 144  ; height: 1500

03-25 19:55:15.464: D/yyyyy(11304): onSizeChanged

03-25 19:55:15.464: I/yyyyy(11304): onLayout --> l: 0  ; r : 144  ; t: 57  ; b: 201  : changed :true

03-25 19:55:15.474: D/yyyyy(11304): onMeasure , width : 1080  ; height: 1557

03-25 19:55:15.474: D/yyyyy(11304): onMeasure , width : 144  ; height: 1500

03-25 19:55:15.474: I/yyyyy(11304): onLayout --> l: 0  ; r : 144  ; t: 57  ; b: 201  : changed :false

03-25 19:55:15.474: D/yyyyy(11304): onDraw--------=====

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))输入日志信息如下:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

03-25 20:37:51.284: E/yyyyy(12530): construct 1 parameter

03-25 20:37:51.294: D/yyyyy(12530): onVisibilityChanged--------=====

03-25 20:37:51.314: D/yyyyy(12530): onVisibilityChanged--------=====

03-25 20:37:51.314: D/yyyyy(12530): onRtlPropertiesChanged--------=====

03-25 20:37:51.314: D/yyyyy(12530): onRtlPropertiesChanged--------=====

03-25 20:37:51.314: E/yyyyy(12530): onAttachedToWindow

03-25 20:37:51.314: D/yyyyy(12530): onWindowVisibilityChanged--------=====

03-25 20:37:51.314: D/yyyyy(12530): onMeasure , width : 1080  ; height: 1557

03-25 20:37:51.314: D/yyyyy(12530): onSizeChanged

03-25 20:37:51.324: I/yyyyy(12530): onLayout --> l: 0  ; r : 1080  ; t: 0  ; b: 1557  : changed :true

03-25 20:37:51.324: D/yyyyy(12530): onMeasure , width : 1080  ; height: 1557

03-25 20:37:51.324: I/yyyyy(12530): onLayout --> l: 0  ; r : 1080  ; t: 0  ; b: 1557  : changed :false

03-25 20:37:51.324: D/yyyyy(12530): onDraw--------=====

03-25 20:37:51.344: D/yyyyy(12530): onWindowFocusChanged--------=====

从测试结果来看,默认情况下view的长和宽默认和父 view 的长和宽一致 。

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

为什么我指定了LayoutParameters,却没有效果?

在不恰当的生命周期中指定LayoutParameters,会被忽略掉,比如如下代码:

?


1

2

3

4

5

6

7

8

9

10

@Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        // setContentView(R.layout.activity_main);

        view = new CusView(this);

        view.setImageResource(R.drawable.ic_launcher);

        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(70, 70);

        view.setLayoutParams(params);

        setContentView(view);

    }

正确的方法应该是放到 onWindowFocusChanged 方法获取到焦点后再指定LayoutParameters,如下代码:

?


1

2

3

4

5

6

7

8

9

10

@Override

    public void onWindowFocusChanged(boolean hasFocus) {

        // TODO Auto-generated method stub

        super.onWindowFocusChanged(hasFocus);

        if (hasFocus) {

            view.setImageResource(R.drawable.ic_launcher);

            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(70, 70);

            view.setLayoutParams(params);

        }

    }

为什么我指定LayoutParameters参数时报异常?异常信息如下:

?


1

java.lang.ClassCastException: android.view.ViewGroup$LayoutParams cannot be cast to android.view.ViewGroup$MarginLayoutParams

java.lang.Object
? android.view.ViewGroup.LayoutParams
  ? android.view.ViewGroup.MarginLayoutParams

LayoutParameters的参数类型不对,从上面继承关系可以看到MarginLayoutParameters扩展了ViewGroup的layoutParameters ,将其修改为任意支持margin动作的LayoutParameters 。

接下来我们看三份销毁 View 的日志:

android:visibility=visible

?


1

2

3

03-25 21:15:35.404: D/yyyyy(14589): onWindowFocusChanged--------=====

03-25 21:15:35.484: D/yyyyy(14589): onWindowVisibilityChanged--------=====

03-25 21:15:35.504: D/yyyyy(14589): onDetachedFromWindow--------=====

android:visibility=gone

?


1

2

3

03-25 21:16:09.964: D/yyyyy(14736): onWindowFocusChanged--------=====

03-25 21:16:10.054: D/yyyyy(14736): onWindowVisibilityChanged--------=====

03-25 21:16:10.064: D/yyyyy(14736): onDetachedFromWindow--------=====

android:visibility=invisible

?


1

2

3

03-25 21:16:42.534: D/yyyyy(14860): onWindowFocusChanged--------=====

03-25 21:16:42.594: D/yyyyy(14860): onWindowVisibilityChanged--------=====

03-25 21:16:42.614: D/yyyyy(14860): onDetachedFromWindow--------=====

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

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

最后给出一小段代码用于在屏幕上拖动view(通过修改view的 layout ):

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

private float mDownX, mDownY, x, y;

    private int dx, dy, il, ir, it, ib;

    @Override

    public boolean onTouchEvent(MotionEvent event) {

        x = event.getX();

        y = event.getY();

        switch (event.getAction()) {

            case MotionEvent.ACTION_DOWN:

                mDownX = event.getX();

                mDownY = event.getY();

                il = getLeft();

                ir = getRight();

                it = getTop();

                ib = getBottom();

                break;

            case MotionEvent.ACTION_MOVE:

            case MotionEvent.ACTION_UP:

                dx += Math.round(x - mDownX);

                dy += Math.round(y - mDownY);

                layout(il + dx, it + dy, ir + dx, ib + dy);

                break;

        }

        return true;

    }

时间: 2024-10-13 21:36:31

Android View的生命周期详解的相关文章

Android之Activity生命周期详解

Activity的生命周期方法: onCreate()--->onStart()--->onResume()--->onPause()--->onStop()--->onDestory() 单个Activity的三种状态:显示状态,不可见状态,销毁状态.1,activity创建到显示要调用前三个方法.2,点击后退键,做了两件事:(1)当前activity被销毁,调用后面三个周期方法.(2)栈中位于最顶部的Activity显示出来.3,onDestory()方法主要是当Acti

Android开发 Activity生命周期详解

前言 在一般情况下了解Activity的生命周期后,都很容易认为自己已经理解了生命周期.并且可能会觉得实际运用起来并不需要这么多的生命周期来处理activity.但是Activity的生命周期的设计理念远远不止是让你知道Activity是在创建还是前台还是在后台或者销毁这般简单.特别是在初始化与释放资源的这难点上,只有深入理解了Activity的生命周期才会让你不会出现各种资源提早释放导致空指针,资源释放失败导致内存泄露,反复初始化导致性能开销大的问题. 生命周期流程图 原文地址:https:/

android四大基础组件--Service生命周期详解

android四大基础组件--ServiceService 生命周期详解 1.Service的生命周期: I> 在非绑定Service情况下,只有oncreate(),onStartCommand(),onDestory()方法情况下:  操作方法对应生命周期一: a.[执行startService(Intent)] 执行生命周期方法:oncreate()--->onStartCommand(): b.[执行stopService(Intent)] 执行生命周期方法:onDestory();

Fragment生命周期详解

Fragment生命周期详解 1. Fragment概述 Fragment从Android v3.0版本开始引入 随着界面布局的复杂化,处理起来也更加的复杂,引入Fragment可以把activity拆分成各个部分.每个Fragment都有它自己的布局和生命周期.方便了开发. 采用fragment而不是activity进行应用的UI管理,可绕开Android系统activity规则的限制. fragment是一种控制器对象,activity可委派它完成一些任务通常这些任务就是管理用户界面.受管的

IOS应用的执行过程以及生命周期详解

iOS的应用程序的生命周期,还有程序是运行在前台还是后台,应用程序各个状态的变换,这些对于开发者来说都是很重要的. iOS系统的资源是有限的,应用程序在前台和在后台的状态是不一样的.在后台时,程序会受到系统的很多限制,这样可以提高电池的使用和用户体验. //开发app,我们要遵循apple公司的一些指导原则,原则如下: 1.应用程序的状态 状态如下: Not running  未运行  程序没启动 Inactive          未激活        程序在前台运行,不过没有接收到事件.在没

ASP.NET生命周期详解 [转]

最近一直在学习ASP.NET MVC的生命周期,发现ASP.NET MVC是建立在ASP.NET Framework基础之上的,所以原来对于ASP.NET WebForm中的很多处理流程,如管道事件等,对于ASP.NET MVC同样适用.只是MVC URLRouting Module对进入到server的request进行了拦截,然后对此次request的handler进行了特殊的处理.总结来说,就是 ASP.NET管道是所有ASP.NET Web Applicaiton,包括WebForm,

struts2.0中Action的对象生命周期详解!!(转)

原文出处:http://blog.csdn.net/wxy_g/article/details/2071662 有很多人问Struts2.0中的对象既然都是线程安全的,都不是单例模式,那么它究竟何时创建,何时销毁呢? 这个和struts2.0中的配置有关,我们来看struts.properties ### if specified, the default object factory can be overridden here ### Note: short-hand notation is

React—组件生命周期详解

React-组件生命周期详解 转自 明明的博客  http://blog.csdn.net/slandove/article/details/50748473 (非原创) 版权声明:转载请注明出处,欢迎加入QQ群(115402375)讨论!博客编写已经转移到http://blog.csdn.net/limm33 在组件的整个生命周期中,随着该组件的props或者state发生改变,它的DOM表现也将有相应的改变,一个组件就是一个状态机,对于特定的输入,它总会返回一致的输出. React为每个组件

Spring Bean的生命周期详解

Spring Bean的生命周期详解 Spring IoC容器的本质目的就是为了管理Bean,对于Bean而言,在容器中存在其生命周期,它的初始化和销毁也需要一个过程,下面主要对其生命周期进行一个详解的解释.生命周期主要是为了了解Spring IoC容器初始化和销毁Bean的过程,通过下图即可以掌握Spring IoC容器初始化与销毁Bean的过程. 通过上图,我们首先可以看到生命周期的步骤. 1)如果Bean实现了接口 BeanNameAware 的 setBeanName 方法,那么它就会调